क्या फॉर्च्यूनर और मैप में अंतर है?


218

ठीक है, यह एक कंप्यूटर विज्ञान का एक प्रश्न है, किसी विशेष भाषा पर आधारित प्रश्न की तुलना में, लेकिन क्या एक मानचित्र संचालन और एक प्रक्षालक ऑपरेशन के बीच अंतर है? या वे बस एक ही चीज़ के लिए अलग-अलग नाम हैं?


उत्सुकता से, अगर मुझे एक Iterator[String]से मिलता है scala.io.Source.fromFile("/home/me/file").getLines()और उस पर लागू .foreach(s => ptintln(s))होता है, तो यह ठीक मुद्रित होता है, लेकिन ठीक बाद खाली हो जाता है। उसी समय अगर मैं .map(ptintln(_))इसे लागू करता हूं - यह सिर्फ खाली हो जाता है और कुछ भी मुद्रित नहीं होता है।
इवान

जवाबों:


294

विभिन्न।

एक सूची से अधिक पुनरावृत्ति

नक्शा एक सूची पर पुनरावृत्ति करता है, उस सूची के प्रत्येक सदस्य को बदल देता है, और रूपांतरित सदस्यों के साथ उसी आकार की एक और सूची लौटाता है (जैसे कि अपरकेस की स्ट्रिंग की सूची परिवर्तित करना)


धन्यवाद, मैंने सोचा कि यह इन पंक्तियों के साथ कुछ था, लेकिन निश्चित नहीं था!
रॉबर्ट गोल्ड

19
लेकिन आप मानचित्र समारोह में भी साइड-इफ़ेक्ट हो सकते हैं। मुझे यह उत्तर पसंद है: stackoverflow.com/a/4927981/375688
TinyTimZamboni

6
उल्लेख करने के लिए एक महत्वपूर्ण बिंदु (यह स्केला में विशेष रूप से सच है) यह है कि जब तक अपेक्षित रूपांतरित सूची को तलब नहीं किया जाता है तब तक इसके अंतर्निहित तर्क के निष्पादन में परिणाम नहींmap होता है। इसके विपरीत, ऑपरेशन की गणना तुरंत की जाती है। foreach
बिग टीटी

124

उनके बीच महत्वपूर्ण अंतर यह है कि mapसभी परिणामों को एक संग्रह में जमा करता है, जबकि foreachकुछ भी नहीं देता है। mapआमतौर पर इसका उपयोग तब किया जाता है जब आप किसी फ़ंक्शन के साथ तत्वों के संग्रह को बदलना चाहते हैं, जबकि foreachबस प्रत्येक तत्व के लिए एक क्रिया निष्पादित करता है।


धन्यवाद! अब मुझे फर्क समझ में आया। यह मेरे लिए कुछ समय के लिए धुंधला हो गया था
रॉबर्ट गोल्ड 20

इसके अलावा बहुत महत्वपूर्ण है!
Мати Тернер

40

संक्षेप में, foreachतत्वों के संग्रह के प्रत्येक तत्व पर एक ऑपरेशन को लागू करने के लिए है, जबकि mapएक संग्रह को दूसरे में बदलने के लिए है।

के बीच foreachऔर दो महत्वपूर्ण अंतर हैं map

  1. foreachयह लागू होने वाले ऑपरेशन पर कोई वैचारिक प्रतिबंध नहीं है, शायद किसी तत्व को तर्क के रूप में स्वीकार करते हैं। यही है, ऑपरेशन कुछ भी नहीं कर सकता है, एक साइड-इफेक्ट हो सकता है, एक मूल्य वापस कर सकता है या एक मूल्य वापस नहीं कर सकता है। सभी foreachपरवाह तत्वों के संग्रह पर पुनरावृति करना है, और प्रत्येक तत्व पर ऑपरेशन लागू करना है।

    mapदूसरी ओर, ऑपरेशन पर प्रतिबंध है: यह एक तत्व को वापस करने के लिए ऑपरेशन की उम्मीद करता है, और शायद एक तत्व को तर्क के रूप में भी स्वीकार करता है। mapआपरेशन तत्वों का एक संग्रह से अधिक iterates, प्रत्येक तत्व पर आपरेशन को लागू करने, और अंत में एक और संग्रह में आपरेशन के प्रत्येक मंगलाचरण का परिणाम भंडारण। दूसरे शब्दों में, एक संग्रह को दूसरे में map बदल देता है

  2. foreachतत्वों के एकल संग्रह के साथ काम करता है। यह इनपुट संग्रह है।

    map तत्वों के दो संग्रह के साथ काम करता है: इनपुट संग्रह और आउटपुट संग्रह।

यह दो एल्गोरिदम से संबंधित करने के लिए एक गलती नहीं है: वास्तव में, आप दो पदानुक्रम को देख सकते हैं, जहां mapकी विशेषज्ञता है foreach। यही है, आप उपयोग कर सकते हैं foreachऔर ऑपरेशन अपने तर्क को बदल सकते हैं और इसे दूसरे संग्रह में डाल सकते हैं। तो, foreachएल्गोरिथ्म एक अमूर्त है, एल्गोरिथ्म का एक सामान्यीकरण map। वास्तव में, क्योंकि foreachइसके संचालन पर कोई प्रतिबंध नहीं है, हम सुरक्षित रूप से कह सकते हैं कि foreachवहां सबसे सरल लूपिंग तंत्र है, और यह कुछ भी कर सकता है जो एक लूप कर सकता है। map, साथ ही अन्य अधिक विशिष्ट एल्गोरिदम, अभिव्यक्ति के लिए है: यदि आप एक संग्रह को दूसरे में मैप करना (या बदलना) चाहते हैं map, तो यदि आप उपयोग करते हैं तो आपका इरादा स्पष्ट है foreach

हम इस चर्चा को आगे बढ़ा सकते हैं, और copyएल्गोरिथ्म पर विचार कर सकते हैं : एक लूप जो एक संग्रह को क्लोन करता है। यह एल्गोरिथ्म भी एल्गोरिथ्म की एक विशेषता foreachहै। आप एक ऑपरेशन को परिभाषित कर सकते हैं, जो एक तत्व दिया गया है, उसी तत्व को दूसरे संग्रह में सम्मिलित करेगा। यदि आप foreachउस ऑपरेशन के साथ प्रयोग करते हैं, तो आपने copyएल्गोरिथ्म का प्रदर्शन किया , भले ही स्पष्टता, स्पष्टता या खोजबीन में कमी आए । आइए इसे और भी आगे ले जाएं: हम कह सकते हैं कि mapएक विशेषज्ञता है copy, स्वयं की एक विशेषज्ञता foreachmapइसमें से कोई भी तत्व बदल सकता है । यदि mapकोई भी तत्व नहीं बदलता है तो यह केवल तत्वों को कॉपी करता है, और कॉपी का उपयोग करता है आशय को अधिक स्पष्ट रूप से व्यक्त करेगा।

foreachएल्गोरिथ्म स्वयं या किसी वापसी मान, भाषा के आधार पर नहीं हो सकता है हो सकता है। उदाहरण के लिए, C ++ में, foreachवह ऑपरेशन लौटाता है जो उसे मूल रूप से प्राप्त हुआ था। विचार यह है कि ऑपरेशन में एक स्थिति हो सकती है, और आप चाहते हैं कि यह ऑपरेशन वापस निरीक्षण कर सके कि यह तत्वों पर कैसे विकसित हुआ। map, भी, मान वापस कर सकता है या नहीं भी कर सकता है। C ++ में transform( mapयहां के लिए समतुल्य ) आउटपुट कंटेनर (संग्रह) के अंत में एक पुनरावृत्तिकर्ता को लौटाने के लिए होता है। रूबी में, का रिटर्न मान mapआउटपुट अनुक्रम (संग्रह) है। तो, एल्गोरिदम का वापसी मूल्य वास्तव में एक कार्यान्वयन विवरण है; उनका असर हो सकता है या नहीं जो वे वापस लौटते हैं।


.forEach()इसे कैसे लागू किया जा सकता है इसका एक उदाहरण के लिए .map(), यहां देखें: stackoverflow.com/a/39159854/1524693
चिनोटो वोक्रो

32

Array.protototype.mapविधि और Array.protototype.forEachदोनों काफी समान हैं।

निम्न कोड चलाएँ: http://labs.codecademy.com/bw1/6#:workspace

var arr = [1, 2, 3, 4, 5];

arr.map(function(val, ind, arr){
    console.log("arr[" + ind + "]: " + Math.pow(val,2));
});

console.log();

arr.forEach(function(val, ind, arr){
    console.log("arr[" + ind + "]: " + Math.pow(val,2));
});

वे सटीक डिट्टो परिणाम देते हैं।

arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25

arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25

लेकिन ट्विस्ट तब आता है जब आप निम्नलिखित कोड चलाते हैं: -

यहां मैंने केवल मानचित्र से और वापसी के तरीकों के परिणाम को सौंपा है।

var arr = [1, 2, 3, 4, 5];

var ar1 = arr.map(function(val, ind, arr){
    console.log("arr[" + ind + "]: " + Math.pow(val,2));
    return val;
});

console.log();
console.log(ar1);
console.log();

var ar2 = arr.forEach(function(val, ind, arr){
    console.log("arr[" + ind + "]: " + Math.pow(val,2));
    return val;
});

console.log();
console.log(ar2);
console.log();

अब परिणाम कुछ मुश्किल है!

arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25

[ 1, 2, 3, 4, 5 ]

arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25

undefined

निष्कर्ष

Array.prototype.mapएक सरणी देता है, लेकिन Array.prototype.forEachनहीं करता है। तो आप मैप विधि में दिए गए कॉलबैक फ़ंक्शन के अंदर दिए गए सरणी को हेरफेर कर सकते हैं और फिर इसे वापस कर सकते हैं।

Array.prototype.forEach केवल दिए गए एरे के माध्यम से चलता है ताकि आप एरे चलते समय अपना सामान कर सकें।


11

सबसे 'दृश्यमान' अंतर यह है कि मानचित्र एक नए संग्रह में परिणाम को जमा करता है, जबकि फॉर्च्यूनर केवल निष्पादन के लिए किया जाता है।

लेकिन कुछ अतिरिक्त धारणाएं हैं: चूंकि मानचित्र का 'उद्देश्य' मूल्यों की नई सूची है, इसलिए यह वास्तव में निष्पादन के आदेश को महत्व नहीं देता है। वास्तव में, कुछ निष्पादन वातावरण समानांतर कोड उत्पन्न करते हैं, या यहां तक ​​कि दोहराया मूल्यों, या आलसीपन के लिए कॉल करने से बचने के लिए कुछ याद करते हैं, कुछ को कॉल करने से बचने के लिए।

दूसरी ओर, फोरचेक को विशेष रूप से दुष्प्रभावों के लिए कहा जाता है; इसलिए आदेश महत्वपूर्ण है, और आमतौर पर इसे समानांतर नहीं किया जा सकता है।


11

संक्षिप्त उत्तर: map और forEachअलग हैं। साथ ही, अनौपचारिक रूप से, mapएक सख्त सुपरसेट है forEach

लंबे उत्तर: पहले, चलो एक पंक्ति के विवरण के साथ आते हैं forEachऔर map:

  • forEach सभी तत्वों पर पुनरावृत्त, प्रत्येक पर आपूर्ति फ़ंक्शन को कॉल करना।
  • map सभी तत्वों पर पुनरावृत्ति करता है, प्रत्येक पर दिए गए फ़ंक्शन को कॉल करता है, और प्रत्येक फ़ंक्शन कॉल के परिणाम को याद करके एक परिवर्तित सरणी का निर्माण करता है।

कई भाषाओं में, forEachअक्सर कहा जाता है each। निम्न चर्चा केवल संदर्भ के लिए जावास्क्रिप्ट का उपयोग करती है। यह वास्तव में कोई अन्य भाषा हो सकती है।

अब, इन कार्यों में से प्रत्येक का उपयोग करते हैं।

का उपयोग कर forEach:

कार्य 1: एक फ़ंक्शन लिखें printSquares, जो संख्याओं की एक सरणी को स्वीकार करता है arr, और इसमें प्रत्येक तत्व के वर्ग को प्रिंट करता है।

समाधान 1:

var printSquares = function (arr) {
    arr.forEach(function (n) {
        console.log(n * n);
    });
};

का उपयोग कर map:

कार्य 2: एक फ़ंक्शन लिखें selfDot, जो संख्याओं की एक सरणी को स्वीकार करता है arr, और एक सरणी देता है जिसमें प्रत्येक तत्व में संबंधित तत्व का वर्ग होता है arr

एक तरफ: यहाँ, कठबोली शब्दों में, हम इनपुट ऐरे को स्क्वायर करने की कोशिश कर रहे हैं। औपचारिक रूप से, हम अपने साथ डॉट उत्पाद की गणना करने की कोशिश कर रहे हैं।

समाधान 2:

var selfDot = function (arr) {
    return arr.map(function (n) {
        return n * n;
    });
};

का mapसुपरसेट कैसे है forEach?

आप टास्क 1 और टास्क 2map दोनों को हल करने के लिए उपयोग कर सकते हैं । हालाँकि, आप टास्क 2 को हल करने के लिए उपयोग नहीं कर सकते ।forEach

में समाधान 1 , अगर आप बस की जगह forEachसे map, समाधान अभी भी मान्य होगा। में समाधान 2 हालांकि, की जगह mapसे forEachअपने पहले से काम कर समाधान टूट जाएगा।

के forEachसंदर्भ में लागू करना map:

अपनी mapश्रेष्ठता को साकार करने का एक और तरीका forEachहै map। जैसा कि हम अच्छे प्रोग्रामर हैं, हम नाम स्थान के प्रदूषण में लिप्त नहीं होंगे। हम अपने फोन करेंगे forEach, बस each

Array.prototype.each = function (func) {
    this.map(func);
};

अब, अगर आपको prototypeबकवास पसंद नहीं है, तो आप यहाँ जाएँ:

var each = function (arr, func) {
    arr.map(func); // Or map(arr, func);
};

तो, उम .. क्यों forEachमौजूद है?

उत्तर दक्षता है। यदि आप किसी सरणी को दूसरे सरणी में बदलने में रुचि नहीं रखते हैं, तो आपको परिवर्तित सरणी की गणना क्यों करनी चाहिए? केवल इसे डंप करने के लिए? बिलकूल नही! यदि आप एक परिवर्तन नहीं चाहते हैं, तो आपको एक परिवर्तन नहीं करना चाहिए।

तो जबकि टास्क 1 को हल करने के लिए मानचित्र का उपयोग किया जा सकता है , यह शायद नहीं होना चाहिए। प्रत्येक के लिए उसके लिए सही उम्मीदवार है।


मूल उत्तर:

जबकि मैं मोटे तौर पर @madlep के जवाब से सहमत हूं, मैं यह बताना चाहता हूं कि map()यह एक सख्त सुपर-सेट है forEach()

हां, map()आमतौर पर एक नई सरणी बनाने के लिए उपयोग किया जाता है। हालाँकि, इसका उपयोग वर्तमान सरणी को बदलने के लिए भी किया जा सकता है।

यहाँ एक उदाहरण है:

var a = [0, 1, 2, 3, 4], b = null;
b = a.map(function (x) { a[x] = 'What!!'; return x*x; });
console.log(b); // logs [0, 1, 4, 9, 16] 
console.log(a); // logs ["What!!", "What!!", "What!!", "What!!", "What!!"]

उपरोक्त उदाहरण में, aआसानी से इस तरह के a[i] === iलिए निर्धारित किया गया था i < a.length। फिर भी, यह शक्ति का प्रदर्शन करता है map()

यहाँ का आधिकारिक वर्णन हैmap() । ध्यान दें कि map()यह उस सरणी को भी बदल सकता है जिस पर इसे कहा जाता है! जय हो map()

आशा है कि इससे मदद मिली।


संपादित 10-Nov-2015: जोड़ा गया विस्तार।


-1, क्योंकि यह केवल जावास्क्रिप्ट के तहत वैध है; जबकि सवाल विशेष रूप से भाषा अज्ञेय और कंप्यूटर विज्ञान अवधारणाओं के बारे में बात करता है, सीमित कार्यान्वयन नहीं।
जेवियर

1
@ जेवियर: हम्म .., मैं आपके उत्तर के बारे में आपसे सहमत होने के लिए सहमत हूं कि जावास्क्रिप्ट विशिष्ट है। लेकिन अपने आप से यह पूछें: अगर किसी भाषा का मूल mapकार्य था, लेकिन नहीं forEach; आप के mapबजाय बस का उपयोग नहीं कर सकता forEach? दूसरी तरफ, यदि कोई भाषा थी, forEachलेकिन नहीं map, तो आपको अपना स्वयं का कार्यान्वयन करना होगा map। आप forEachइसके बजाय बस का उपयोग नहीं कर सकते map। मुझे बताओ तुम क्या सोचते हो।
सुमुख बर्वे

3

यहाँ सूचियों का उपयोग करके स्काला में एक उदाहरण दिया गया है: मैप रिटर्न लिस्ट, फ़ॉरचैट रिटर्न कुछ नहीं।

def map(f: Int ⇒ Int): List[Int]
def foreach(f: Int ⇒ Unit): Unit

इसलिए मानचित्र प्रत्येक सूची तत्व में फ़ंक्शन एफ को लागू करने के परिणामस्वरूप सूची लौटाता है:

scala> val list = List(1, 2, 3)
list: List[Int] = List(1, 2, 3)

scala> list map (x => x * 2)
res0: List[Int] = List(2, 4, 6)

Foreach बस प्रत्येक तत्व पर लागू होता है:

scala> var sum = 0
sum: Int = 0

scala> list foreach (sum += _)

scala> sum
res2: Int = 6 // res1 is empty

2

यदि आप विशेष रूप से जावास्क्रिप्ट के बारे में बात कर रहे हैं, तो अंतर यह है कि mapएक लूप फ़ंक्शन है, जबकि forEachएक पुनरावृत्ति है।

mapजब आप सूची के प्रत्येक सदस्य के लिए एक ऑपरेशन लागू करना चाहते हैं और मूल सूची को प्रभावित किए बिना एक नई सूची के रूप में वापस परिणाम प्राप्त करना चाहते हैं, का उपयोग करें ।

का प्रयोग करें forEachजब आप करना चाहते हैं कर सूची के प्रत्येक तत्व के आधार पर कुछ। उदाहरण के लिए, आप चीजों को पृष्ठ में जोड़ सकते हैं। अनिवार्य रूप से, जब आप "दुष्प्रभाव" चाहते हैं तो यह बहुत अच्छा है।

अन्य अंतर: forEachकुछ भी नहीं लौटाता है (क्योंकि यह वास्तव में एक नियंत्रण प्रवाह समारोह है), और पारित फ़ंक्शन को सूचकांक और पूरी सूची का संदर्भ मिलता है, जबकि नक्शा नई सूची देता है और केवल वर्तमान तत्व में गुजरता है।


0

फॉरएड आरडीडी के प्रत्येक तत्व पर डीबी आदि लिखने के लिए एक फ़ंक्शन लागू करने की कोशिश करता है, बिना कुछ वापस किए।

लेकिन map()rdd के तत्वों पर कुछ फ़ंक्शन लागू करता है और rdd को लौटाता है। इसलिए जब आप नीचे दी गई विधि को चलाते हैं तो यह लाइन 3 पर विफल नहीं होगा, लेकिन फॉर्चून लगाने के बाद आरडीडी एकत्र करते समय यह विफल हो जाएगा और आज एक त्रुटि फेंक देगा।

फ़ाइल "<stdin>", पंक्ति 5, में <मॉड्यूल>

गुण: 'कोई नहीं' वस्तु का कोई गुण नहीं 'संग्रह' है

nums = sc.parallelize([1,2,3,4,5,6,7,8,9,10])
num2 = nums.map(lambda x: x+2)
print ("num2",num2.collect())
num3 = nums.foreach(lambda x : x*x)
print ("num3",num3.collect())
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.