2011-03-10 35 views
349

मैंने इसे गुगल किया है और पैची/विरोधाभासी राय प्राप्त की है - क्या वास्तव में map करने और रूबी/रेल में एक सरणी पर collect करने के बीच कोई अंतर है?रूबी में मानचित्र और संग्रह के बीच अंतर?

docs किसी भी सुझाव का सुझाव नहीं लगता है, लेकिन क्या शायद विधि या प्रदर्शन में अंतर है?

+3

'नक्शा' को [कोड गोल्फ] (http://codegolf.stackexchange.com/questions) पर प्राथमिकता दी जाती है। –

+1

कोडगॉल्फ में 'मैप' क्यों पसंद किया जाता है, इसकी व्याख्या के रूप में, जो सभी के लिए स्पष्ट नहीं हो सकता है: यह केवल इसलिए है क्योंकि' संग्रह ''नक्शा' से चार वर्ण लंबा है, लेकिन कार्यक्षमता में समान है। –

उत्तर

401

वहाँ कोई अंतर नहीं है, वास्तव में maprb_ary_collect और enum_collect के रूप में सी में कार्यान्वित किया जाता है (उदाहरण के लिए। वहाँ एक सरणी पर और किसी भी अन्य enum पर map बीच एक अंतर है, लेकिन map और collect के बीच कोई अंतर) ।


क्यों दोनों map करते हैं और collect रूबी में मौजूद हैं?map फ़ंक्शन में विभिन्न भाषाओं में कई नामकरण सम्मेलन हैं। Wikipedia provides an overview:

नक्शा समारोह कार्यात्मक प्रोग्रामिंग भाषाओं में जन्म लिया है लेकिन आज समर्थित (या में परिभाषित किया जा सकता है) कई प्रक्रियात्मक, वस्तु उन्मुख, और बहु-प्रतिमान भाषाओं में भी है: सी ++ के मानक टेम्पलेट लायब्रेरी में, यह कहा जाता है transform, सी # (3.0) की LINQ लाइब्रेरी में, इसे Select नामक एक विस्तार विधि के रूप में प्रदान किया जाता है। नक्शा भी पर्ल, पायथन और रूबी जैसे उच्च स्तरीय भाषाओं में अक्सर इस्तेमाल किया जाने वाला ऑपरेशन होता है; इन तीनों भाषाओं में ऑपरेशन को map कहा जाता है। collect नक्शा के लिए उपनाम रूबी (स्मॉलटाक से) [जोर मेरा] में भी प्रदान किया जाता है। सामान्य लिस्प मानचित्र के समान कार्यों का एक परिवार प्रदान करता है; यहां वर्णित व्यवहार से संबंधित एक को mapcar कहा जाता है (-कर कार ऑपरेशन का उपयोग करके पहुंच का संकेत देता है)।

रूबी छोटे घर की दुनिया से प्रोग्रामर के लिए घर पर अधिक महसूस करने के लिए एक उपनाम प्रदान करता है।


क्यों सरणियों और enums के लिए एक अलग कार्यान्वयन है? एक enum एक सामान्यीकृत पुनरावृत्ति संरचना है, जिसका अर्थ है कि रूबी भविष्यवाणी कर सकता है कि अगला तत्व क्या हो सकता है (आप अनंत enums को परिभाषित कर सकते हैं, उदाहरण के लिए Prime देखें)। इसलिए इसे प्रत्येक क्रमिक तत्व प्राप्त करने के लिए एक फ़ंक्शन को कॉल करना होगा (आमतौर पर यह each विधि होगी)।

सरणी सबसे आम संग्रह कर रहे हैं तो यह उनके प्रदर्शन को अनुकूलित करने के लिए उचित है। चूंकि रूबी इस बारे में बहुत कुछ जानता है कि एरे कैसे काम करते हैं, इसे each पर कॉल करने की आवश्यकता नहीं है, लेकिन केवल सरल pointer manipulation का उपयोग कर सकते हैं जो काफी तेज़ है।

इसी तरह के अनुकूलन zip या count जैसे कई ऐरे विधियों के लिए मौजूद हैं।

+8

@ मार्क रीड लेकिन फिर, प्रोग्रामर जो स्मॉलटाक से नहीं आ रहे हैं, वे दो अलग-अलग कार्यों के साथ भ्रमित होंगे, जो सिर्फ उपनाम होने के लिए निकलते हैं। यह उपरोक्त ओपी जैसे प्रश्नों का कारण बनता है। – SasQ

+7

@SasQ मैं असहमत नहीं हूं - मुझे लगता है कि अगर केवल एक ही नाम था तो यह बेहतर होगा। लेकिन रूबी में कई अन्य उपनाम हैं, और एलियासिंग की एक विशेषता यह है कि संचालन * संग्रह *, * पता *, * इंजेक्ट *, * अस्वीकार *, और * चयन * (अन्यथा के रूप में जाना जाता है) के बीच समानांतर नामकरण है * नक्शा *, * ढूंढें *, * कम करें *, * अस्वीकार करें * (कोई उपनाम नहीं), और * find_all *)। वास्तव में –

+2

। जाहिर है, रूबी अधिक अवसरों पर उपनाम/समानार्थी शब्द का उपयोग कर रहा है। उदाहरण के लिए, सरणी में तत्वों की संख्या को 'गिनती', 'लंबाई', या 'आकार' के साथ पुनर्प्राप्त किया जा सकता है। एक सरणी के समान गुण के लिए अलग-अलग शब्द, लेकिन इसके द्वारा, रूबी आपको अपने कोड के लिए सबसे उपयुक्त शब्द चुनने में सक्षम बनाता है: क्या आप अपने द्वारा एकत्र किए जा रहे आइटमों के _number_, सरणी के _length_, या वर्तमान _size_ के मौजूदा _size_ चाहते हैं संरचना। अनिवार्य रूप से, वे सभी समान हैं, लेकिन सही शब्द चुनने से आपका कोड पढ़ने में आसान हो सकता है, जो भाषा की एक अच्छी संपत्ति है। –

41

मुझे बताया गया है कि वे समान हैं।

असल में वे ruby-doc.org के तहत एक ही स्थान पर प्रलेखित हैं:

http://www.ruby-doc.org/core/classes/Array.html#M000249

  • ary.collect {| मद | ब्लॉक} → new_ary
  • ary.map {| item | ब्लॉक} → new_ary
  • ary.collect → an_enumerator
  • ary.map → an_enumerator

invokes ब्लॉक एक बार स्वयं के प्रत्येक तत्व के लिए। ब्लॉक द्वारा लौटाए गए मानों वाला एक नया सरणी बनाता है। भी संख्यात्मक # संग्रह देखें।
यदि कोई ब्लॉक नहीं दिया गया है, तो इसके बजाय एक गणनाकर्ता लौटा दिया जाता है।

a = [ "a", "b", "c", "d" ] 
a.collect {|x| x + "!" } #=> ["a!", "b!", "c!", "d!"] 
a       #=> ["a", "b", "c", "d"] 
+1

बस पूरी तरह से होने के लिए: [http://www.ruby-doc.org/core/classes/Enumerable.html#method-i-map](http://www.ruby-doc.org/core/classes/ Enumerable.html # विधि-i-map) –

6

रूबी ऐरे # संग्रह के लिए ऐरे # मानचित्र विधि को उपनाम करता है; वे एक दूसरे के लिए इस्तेमाल किया जा सकता है। (रूबी भिक्षु)

दूसरे शब्दों में, एक ही स्रोत कोड में:

   static VALUE 
rb_ary_collect(VALUE ary) 
{ 
long i; 
VALUE collect; 

RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length); 
collect = rb_ary_new2(RARRAY_LEN(ary)); 
for (i = 0; i < RARRAY_LEN(ary); i++) { 
    rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i))); 
} 
return collect; 
} 

http://ruby-doc.org/core-2.2.0/Array.html#method-i-map

+0

मैं चाहता हूं कि प्रलेखन स्पष्ट रूप से बताए कि वे उपनाम हैं। फिलहाल वे एक दूसरे का संदर्भ देते हैं, और दोनों के पास थोड़ा अलग विवरण हैं। –

5

मैं कोशिश करते हैं और इस सवाल का जवाब करने के लिए एक बेंचमार्क परीक्षण किया, तो पाया इस पोस्ट इसलिए यहाँ मेरी निष्कर्ष (हैं जो अन्य उत्तर से थोड़ा भिन्न होते हैं)

यहाँ बेंचमार्क कोड है:

require 'benchmark' 

h = { abc: 'hello', 'another_key' => 123, 4567 => 'third' } 
a = 1..10 
many = 500_000 

Benchmark.bm do |b| 
    GC.start 

    b.report("hash keys collect") do 
    many.times do 
     h.keys.collect(&:to_s) 
    end 
    end 

    GC.start 

    b.report("hash keys map") do 
    many.times do 
     h.keys.map(&:to_s) 
    end 
    end 

    GC.start 

    b.report("array collect") do 
    many.times do 
     a.collect(&:to_s) 
    end 
    end 

    GC.start 

    b.report("array map") do 
    many.times do 
     a.map(&:to_s) 
    end 
    end 
end 

और परिणाम मुझे मिल रहे थे:

    user  system  total  real 
hash keys collect 0.540000 0.000000 0.540000 ( 0.570994) 
hash keys map  0.500000 0.010000 0.510000 ( 0.517126) 
array collect  1.670000 0.020000 1.690000 ( 1.731233) 
array map   1.680000 0.020000 1.700000 ( 1.744398) 

शायद एक उपनाम मुक्त नहीं है?

संबंधित मुद्दे