रूबी में "मैप" विधि क्या करती है?


250

मैं प्रोग्रामिंग में नया हूँ। क्या कोई समझा सकता है कि इसमें क्या .mapहोगा:

params = (0...param_count).map

9
एक बार में एक प्रश्न पूछें । mapएक सामान्य "कार्यात्मक" विधि है, जो एक अनुक्रम में मूल्यों को बदलने के लिए उपयोग की जाने वाली Enumerable वस्तुओं पर पाई जाती है (विशेष विचारों के साथ)। ..और ...रेंज बनाने के तरीके हैं। इसके अलावा, आरईपीएल से परिचित हों , जहां आप इस सामान को खुद आज़मा सकते हैं! :)

5
माणिक के लिए आरईपीएल आईआरबी है, रेल के लिए यह रेल सी है। REPL आपको सीधे भाषा शेल के खिलाफ कोड का परीक्षण करने की अनुमति देता है।
गैरी

जवाबों:


431

mapविधि एक गणनीय वस्तु और एक ब्लॉक लेता है, और प्रत्येक तत्व के लिए ब्लॉक चलाता है, (मूल वस्तु में कोई बदलाव नहीं है जब तक कि आप का उपयोग ब्लॉक से प्रत्येक दिए गए मान outputting map!):

[1, 2, 3].map { |n| n * n } #=> [1, 4, 9]

Arrayऔर Rangeenumerable प्रकार हैं। mapएक ब्लॉक के साथ एक ऐरे देता है। map!मूल सरणी को बदल देता है।

इस कहाँ उपयोगी है, और के बीच अंतर क्या है map!और each? यहाँ एक उदाहरण है:

names = ['danil', 'edmund']

# here we map one array to another, convert each element by some rule
names.map! {|name| name.capitalize } # now names contains ['Danil', 'Edmund']

names.each { |name| puts name + ' is a programmer' } # here we just do something with each element

उत्पादन:

Danil is a programmer
Edmund is a programmer

3
उदाहरण के लिए धन्यवाद speransky। तो .map कैसे .each से अलग है?
Bigpotato

2
आहह मैं समझ गई। तो .map वास्तव में सरणी को बदल देता है। जबकि मूल सरणी को अछूता छोड़ने के लिए मूल्यों तक पहुंचने के लिए केवल सरणी के माध्यम से लूप करता है?
Bigpotato

24
यह आकस्मिक पाठकों के लिए खतरनाक है कि उद्घाटन वाक्य में वर्णित है mapजैसे कि यह थाmap!
kaleidic

12
मानचित्र और प्रत्येक के बीच अंतर देखने के लिए, एक IRB विंडो खोलें और निम्नलिखित कोड में y और z के परिणाम देखें: y = [1,2,3] .each {| x | x + 1}; z = [1,2,3] .मैप {| x | x + 1}
dvj

7
@ जिज्ञासु: 'प्रत्येक' उस सरणी को लौटाता है जो इसे कहता है (उदाहरण में, [1,2,3]) जब एक ब्लॉक की आपूर्ति की जाती है, तो 'मैप' ब्लॉक द्वारा गणना किए गए मानों के साथ आबाद एक नया सरणी देता है। यह मदद कर सकता है: चर एरी = [1,2,3] सेट करें, और देखें कि यह ऑब्जेक्ट_ड है। फिर y = ary.each {| x | x + 1}; z = ary.map {| x | x + 1}। अब y और z के object_id की जाँच करें। y में समान ऑब्जेक्ट_id है ary (क्योंकि प्रत्येक ने ary लौटाया है), लेकिन z में एक अलग object_id है, क्योंकि मानचित्र ने एक नया सरणी लौटाया है।
davej

66

mapके साथ-साथ selectऔर eachमेरे कोड में रूबी के workhorses से एक है।

यह आपको अपने प्रत्येक सरणी के ऑब्जेक्ट पर एक ऑपरेशन चलाने और सभी को एक ही स्थान पर वापस करने की अनुमति देता है। एक उदाहरण के लिए एक के बाद एक संख्या बढ़ाना होगा:

[1,2,3].map {|x| x + 1 }
#=> [2,3,4]

यदि आप अपने सरणी के तत्वों पर एक एकल विधि चला सकते हैं, तो आप इसे शॉर्टहैंड-स्टाइल में कर सकते हैं:

  1. उपरोक्त उदाहरण के साथ ऐसा करने के लिए आपको कुछ ऐसा करना होगा

    class Numeric
      def plusone
        self + 1
      end
    end
    [1,2,3].map(&:plusone)
    #=> [2,3,4]
  2. एम्परसेंड शॉर्टकट तकनीक का अधिक उपयोग करने के लिए, आइए एक अलग उदाहरण का उपयोग करें:

    ["vanessa", "david", "thomas"].map(&:upcase)
    #=> ["VANESSA", "DAVID", "THOMAS"]

रूबी में डेटा ट्रांसफ़ॉर्म करने में अक्सर mapऑपरेशन का झरना शामिल होता है । अध्ययन mapऔर select, वे प्राथमिक पुस्तकालय में सबसे उपयोगी रूबी विधियों में से कुछ हैं। वे बस के रूप में महत्वपूर्ण के रूप में कर रहे हैं each

( mapइसके लिए एक उपनाम भी है collect। वैचारिक रूप से आपके लिए जो भी सबसे अच्छा काम करता है उसका उपयोग करें।)

अधिक उपयोगी जानकारी:

यदि आपके द्वारा चलाए जा रहे Enumerable ऑब्जेक्ट eachया mapEnumerable तत्वों (hashes, arrays) का एक सेट होता है, तो आप अपने ब्लॉक पाइप के अंदर उन तत्वों में से प्रत्येक को घोषित कर सकते हैं जैसे:

[["audi", "black", 2008], ["bmw", "red", 2014]].each do |make, color, year|
  puts "make: #{make}, color: #{color}, year: #{year}"
end
# Output:
# make: audi, color: black, year: 2008
# make: bmw, color: red, year: 2014

हाश के मामले में (एक Enumerableवस्तु भी , एक हैश केवल दुभाषिया के लिए विशेष निर्देशों के साथ ट्यूपल्स की एक सरणी है)। पहला "पाइप पैरामीटर" कुंजी है, दूसरा मूल्य है।

{:make => "audi", :color => "black", :year => 2008}.each do |k,v|
    puts "#{k} is #{v}"
end
#make is audi
#color is black
#year is 2008

वास्तविक प्रश्न का उत्तर देने के लिए:

मान लें कि paramsयह एक हैश है, तो इसके माध्यम से मैप करने का यह सबसे अच्छा तरीका होगा: हैश में प्रत्येक व्याख्या किए गए टपल के लिए कुंजी और मान युग्म को पकड़ने के लिए एक के बजाय दो ब्लॉक पैरामीटर का उपयोग करें।

params = {"one" => 1, "two" => 2, "three" => 3}
params.each do |k,v|
  puts "#{k}=#{v}"
end
# one=1
# two=2
# three=3

यह मेरे लिए irb में काम नहीं करता है। मैं NoMethodError: private method 'plusone' called for 1:Fixnumरूबी में 2 / 'गलत संख्या में args' 1.9 / 1.8 में मिलता हूं । वैसे भी, मैंने एक लैम्ब्डा का उपयोग किया है: plusone = ->(x) { x + 1 }फिर प्रतीक विनिर्देशक को बाहर निकालें [1,2,3].map(&plusone):।
tjmcewan

1
हम्म की तरह लगता है जैसे आपने privateकक्षा के अंदर घोषित किया जहाँ आप अपना तरीका
डालते हैं

हाँ, यह पूरी तरह से करता है। सिवाय इसके कि यह नहीं था। :( सबसे पहले यह एक सीधी स्क्रिप्ट w / o क्लासेस में था, दूसरा सीधे सादे irb में। यहाँ मेरी कॉपी / आपके कोड का पेस्ट है: gist.github.com/tjmcewan/a7e4feb2976a93aaaeef9
tjmcewan

हाँ, मैंने पूरी तरह से अपने कोड में एक बुरा उदाहरण दिया है मुझे क्षमा करें। संशोधित कोड का प्रयास करें। अब यह काम करता है ...
boulder_ruby

1
@boulder_ruby एक सामान्य विधि के साथ ऐसा करने का एक तरीका है - जैसा कि, वर्ग विधि नहीं है?
टेकनकोलागी

6

रूबी 2.4 का उपयोग करके आप एक ही काम कर सकते हैं transform_values, यह सुविधा रेल से रूबी तक निकाली गई है।

h = {a: 1, b: 2, c: 3}

h.transform_values { |v| v * 10 }
 #=> {a: 10, b: 20, c: 30}

4

0..param_countका अर्थ है "और param_count सहित"। 0...param_countका अर्थ है "अप करने के लिए, लेकिन param_count शामिल नहीं"।

Range#mapएक वापस नहीं करता है Enumerable, यह वास्तव में इसे एक सरणी में मैप करता है। यह वैसा ही है Range#to_a


3

यह प्रत्येक आइटम को "मैप" करता है Enumerable- इस मामले में, एक सीमा। तो यह प्रत्येक पूर्णांक के लिए 0 param_count(अनन्य - आप डॉट्स के बारे में सही हो) के लिए एक बार पास किए गए ब्लॉक को कॉल करेगा और एक सरणी लौटाएगा जिसमें आपका रिटर्न मान होगा।

यहाँ के लिए प्रलेखन है Enumerable#mapयह भी एक उपनाम है, collect


यह अजीब है, लेकिन Range#mapवास्तव में इसे एक सरणी में परिवर्तित करता है।
पेड्रो नैसिंमेंटो

1
@PedroNascimento: हाँ ... यही मैंने कहा है?
Ry-

क्षमा करें, मुझे पता नहीं था कि Enumerableप्रत्येक द्वारा बुलाया गया नक्शा प्रत्येक की तरह वापस नहीं आया । मुझे लगा कि यह किया है।
पेड्रो नासिमेंटो

2

मैप एन्युमरेबल मॉड्यूल का एक हिस्सा है। उदाहरण के लिए "इकट्ठा" के समान:

  Class Car

    attr_accessor :name, :model, :year

    Def initialize (make, model, year)
      @make, @model, @year = make, model, year
    end

  end

  list = []
  list << Car.new("Honda", "Accord", 2016)
  list << Car.new("Toyota", "Camry", 2015)
  list << Car.new("Nissan", "Altima", 2014)

  p list.map {|p| p.model}

मानचित्र एक मान के माध्यम से पुनरावृत्ति करने वाले मान प्रदान करता है जो ब्लॉक मापदंडों द्वारा वापस किए जाते हैं।


नक्शा बिलकुल वैसा ही है जैसा कि संग्रह।
BKSpurgeon

0

#each

#eachएक सरणी में प्रत्येक तत्व के लिए एक फ़ंक्शन चलाता है। निम्नलिखित दो कोड अंश समकक्ष हैं:

x = 10
["zero", "one", "two"].each{|element|
    x++
    puts element
}
x = 10
array = ["zero", "one", "two"]

for i in 0..2
    x++
    puts array[i]
end

#map

#mapएक सरणी के प्रत्येक तत्व पर एक फ़ंक्शन लागू करता है, जिसके परिणामस्वरूप सरणी वापस आती है। निम्नलिखित समतुल्य हैं:

array = ["zero", "one", "two"]
newArray = array.map{|element| element.capitalize()}
array = ["zero", "one", "two"]

newArray = []
array.each{|element|
    newArray << element.capitalize()
}

#map!

#map!की तरह है #map, लेकिन जगह में सरणी को संशोधित करता है। निम्नलिखित समतुल्य हैं:

array = ["zero", "one", "two"]
array.map!{|element| element.capitalize()}
array = ["zero", "one", "two"]
array = array.map{|element| element.capitalize()}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.