Array_map, array_walk और array_filter के बीच अंतर


373

वास्तव में क्या अंतर है array_map, array_walkऔरarray_filter । प्रलेखन से जो मैं देख सकता था वह यह है कि आप आपूर्ति की गई सरणी पर कार्रवाई करने के लिए कॉलबैक फ़ंक्शन पास कर सकते हैं। लेकिन मुझे उनके बीच कोई विशेष अंतर नहीं लगता है।

क्या वे एक ही कार्य करते हैं?
क्या उनका परस्पर उपयोग किया जा सकता है?

मैं उदाहरण के साथ आपकी मदद की सराहना करता हूं अगर वे बिल्कुल अलग हैं।


यह array_reduce () के माध्यम से नाम प्रसंस्करण के लिए एक शांत चाल है। यदि आप array_map, array_walk, और array_filter की जांच कर रहे हैं तो पढ़ने के लायक हो जाएं। stackoverflow.com/questions/11563119/…
लांस क्लीवलैंड

जवाबों:


564
  • बदलते मूल्य:
    • array_mapइनपुट ऐरे (एस) के अंदर मूल्यों को बदल नहीं array_walkसकते, जबकि ; विशेष रूप से, array_mapअपने तर्कों को कभी नहीं बदलता है।
  • ऐरे कीज़ एक्सेस:
    • array_mapसरणी कुंजियों के साथ काम नहीं array_walkकर सकता।
  • प्रतिलाभ की मात्रा:
    • array_mapएक नया सरणी array_walkदेता है , केवल लौटता है true। इसलिए, यदि आप किसी एक सरणी को ट्रेस करने के परिणामस्वरूप कोई सरणी नहीं बनाना चाहते हैं, तो आपको उपयोग करना चाहिए array_walk
  • एकाधिक सारणियों को बदलना:
    • array_mapकेवल सरणियों की एक मनमानी संख्या प्राप्त कर सकते हैं और यह समानांतर में उन पर पुनरावृति कर सकता है, जबकि array_walkकेवल एक पर संचालित होता है।
  • कॉलबैक में मनमाना डेटा पास करना:
    • array_walkकॉलबैक को पास करने के लिए एक अतिरिक्त मनमाना पैरामीटर प्राप्त कर सकते हैं। यह ज्यादातर PHP 5.3 (जब अनाम फ़ंक्शंस के बाद से अप्रासंगिक है) पेश किए गए थे) के ।
  • लौटे एरे की लंबाई:
    • परिणामी सरणी की array_mapलंबाई सबसे बड़ी इनपुट सरणी के समान है; array_walkएक सरणी वापस नहीं करता है, लेकिन एक ही समय में यह मूल सरणी के तत्वों की संख्या को बदल नहीं सकता है; array_filterएक फ़िल्टरिंग फ़ंक्शन के अनुसार सरणी के तत्वों का केवल एक सबसेट चुनता है। यह कुंजी को संरक्षित करता है।

उदाहरण:

<pre>
<?php

$origarray1 = array(2.4, 2.6, 3.5);
$origarray2 = array(2.4, 2.6, 3.5);

print_r(array_map('floor', $origarray1)); // $origarray1 stays the same

// changes $origarray2
array_walk($origarray2, function (&$v, $k) { $v = floor($v); }); 
print_r($origarray2);

// this is a more proper use of array_walk
array_walk($origarray1, function ($v, $k) { echo "$k => $v", "\n"; });

// array_map accepts several arrays
print_r(
    array_map(function ($a, $b) { return $a * $b; }, $origarray1, $origarray2)
);

// select only elements that are > 2.5
print_r(
    array_filter($origarray1, function ($a) { return $a > 2.5; })
);

?>
</pre>

परिणाम:

Array
(
    [0] => 2
    [1] => 2
    [2] => 3
)
Array
(
    [0] => 2
    [1] => 2
    [2] => 3
)
0 => 2.4
1 => 2.6
2 => 3.5
Array
(
    [0] => 4.8
    [1] => 5.2
    [2] => 10.5
)
Array
(
    [1] => 2.6
    [2] => 3.5
)

3
PHP मैनुअल कहता है: "array_walk (): केवल सरणी के मान को संभवतः बदला जा सकता है;"
27

10
"array_map सरणी कुंजियों के साथ काम नहीं कर सकता है" यह सच नहीं है:array_map(callback($key, $value), array_keys($array), $array)
Jarek Jakubowski

12
यह अभी भी किसी भी ऐरे की कुंजियों तक नहीं पहुंच रहा है, यह उन मूल्यों को स्वीकार कर रहा है जो आपने ऐरे में बनाए हैं। यह एक वर्कअराउंड है, यह कथन को नकारता नहीं है।
इनरिलो

जबकि array_map समान रूप से मानों को नहीं बदलता है, उसी सरणी के परिणाम को मूल रूप से बदलकर इसे बदल देता है, और 'विरोधाभासी रूप से' array_walk जो उसी सरणी पर संचालित होता है, अपने मूल्यों को सीधे नहीं बदलेगा, जब तक कि संदर्भ द्वारा मान पारित नहीं किया जाता है (सरणी) वॉक अनुक्रमणिका / तत्वों को हटा सकता है क्योंकि array_filter अप्रत्यक्ष रूप से अनाम फ़ंक्शन के माध्यम से मूल सरणी से गुजरने वाले क्लॉज का उपयोग करता है लेकिन यह एक वर्कअराउंड है)। इस प्रकार, निष्कर्ष बदलने के लिए, और न ही यदि कोई मान लौटाया जाता है या संदर्भ से पारित किया जाता है, तो प्रभावी रूप से कम अंतर होता है, लेकिन सरणी सारणी कई सारणियों के साथ अनुक्रमित और सरणी मानचित्र के साथ काम करती है
FentomX1

इसके अलावा ऐसा लगता है कि कोई फर्क नहीं पड़ता कि सरणी चलना एक संदर्भ के रूप में पहला, सरणी पैरामीटर लेता है, जब कोई इसे बदलना चाहता है तो उसे कॉलबैक आइटम मान भी एक संदर्भ के रूप में पास करना होगा
FentomX1

91

फ़ंक्शन को डेटा की सरणी में मैप करने का विचार कार्यात्मक प्रोग्रामिंग से आता है। आपको array_mapएक foreachलूप के रूप में नहीं सोचना चाहिए जो सरणी के प्रत्येक तत्व पर एक फ़ंक्शन कहता है (भले ही यह कैसे लागू हो)। यह सरणी में प्रत्येक तत्व को स्वतंत्र रूप से फ़ंक्शन को लागू करने के रूप में सोचा जाना चाहिए।

सिद्धांत रूप में फ़ंक्शन मैपिंग जैसी चीजें समानांतर रूप से की जा सकती हैं क्योंकि फ़ंक्शन को डेटा पर लागू किया जाना चाहिए केवल डेटा को प्रभावित करना चाहिए और वैश्विक स्थिति को नहीं। ऐसा इसलिए है क्योंकि कोई array_mapभी ऑर्डर चुन सकता है जिसमें फ़ंक्शन को आइटम में लागू करने के लिए (भले ही PHP में यह नहीं है)।

array_walkदूसरी ओर यह डेटा की सरणियों को संभालने के लिए सटीक विपरीत दृष्टिकोण है। प्रत्येक आइटम को अलग-अलग संभालने के बजाय, यह एक राज्य ( &$userdata) का उपयोग करता है और आइटम को जगह में संपादित कर सकता है (बहुत कुछ एक फ़ॉर्च लूप की तरह)। चूंकि हर बार किसी आइटम ने उस पर $funcnameलागू किया है, इसलिए यह कार्यक्रम की वैश्विक स्थिति को बदल सकता है और इसके लिए वस्तुओं को संसाधित करने का एक सही तरीका आवश्यक है ।

PHP भूमि में वापस, array_mapऔर array_walkलगभग समान हैं, सिवाय इसके array_walkकि आप डेटा के पुनरावृत्ति पर अधिक नियंत्रण प्रदान करते हैं और आमतौर पर डेटा को इन-प्लेस करने के लिए उपयोग किया जाता है बनाम एक नया "परिवर्तित" सरणी वापस लौटाया जाता है।

array_filterवास्तव में array_walk(या array_reduce) का एक अनुप्रयोग है और यह अधिक-या-कम सिर्फ सुविधा के लिए प्रदान किया गया है।


5
+1 आपकी दूसरी अनुच्छेद जानकारी के लिए "सिद्धांत रूप में फ़ंक्शन मैपिंग जैसी चीजें समानांतर रूप से की जा सकती हैं क्योंकि फ़ंक्शन को डेटा पर लागू किया जाना चाहिए केवल डेटा को प्रभावित करना चाहिए और वैश्विक स्थिति को नहीं।" हमारे लिए समानांतर प्रोग्रामर, यह ध्यान में रखने के लिए एक उपयोगी चीज है।
ईथर

क्या आप बता array_filter()सकते हैं कि इसका उपयोग कैसे लागू किया जा सकता है array_walk()?
pfrenssen

40

प्रलेखन से,

बूल array_walk (सरणी और $ ऐरे, कॉलबैक $ funcname [, मिश्रित $ userdata]) <-पूर्ण मल

array_walk एक एरे और एक फंक्शन लेता है Fऔर इसे हर एलिमेंट x को रिप्लेस करके मॉडिफाई करता है F(x)

सरणी array_map (कॉलबैक $ कॉलबैक, सरणी $ arr1 [, सरणी $ ...]) <- वापसी सरणी

array_map ठीक वही काम करता है, सिवाय इसके कि वह इन-प्लेस को संशोधित करने के बजाय परिवर्तित तत्वों के साथ एक नया सरणी लौटाएगा।

सरणी array_filter (सरणी $ इनपुट [, कॉलबैक $ कॉलबैक]) <- वापसी सरणी

array_filter फ़ंक्शन के साथ F, तत्वों को बदलने के बजाय, किसी भी ऐसे तत्व को हटा देगा जिसके लिए F(x)सत्य नहीं है


पता नहीं चल सका कि मेरे सरणी मान क्यों गायब हो गए। दस्तावेज़ीकरण को देखते हुए मैंने मान लिया कि यह array_walkएक सरणी है array_mapऔर मुझे लगा कि यह समस्या मेरे कार्य में है। एहसास नहीं हुआ जब तक मैंने यह नहीं देखा कि वापसी का प्रकार बूलियन है।
डायलन वालडे

22

अन्य उत्तर array_walk (इन-प्लेस मॉडिफिकेशन) और array_map (वापसी संशोधित प्रति) के बीच अंतर को काफी अच्छी तरह से प्रदर्शित करते हैं। हालांकि, वे वास्तव में array_reduce का उल्लेख नहीं करते हैं, जो array_map और array_filter को समझने का एक शानदार तरीका है।

Array_reduce फ़ंक्शन इस तरह से एक सरणी, एक दो-तर्क फ़ंक्शन और एक 'संचायक' लेता है:

array_reduce(array('a', 'b', 'c', 'd'),
             'my_function',
             $accumulator)

दिए गए फ़ंक्शन का उपयोग करके सरणी के तत्वों को एक समय में संचायक के साथ जोड़ा जाता है। उपरोक्त कॉल का परिणाम ऐसा करने के समान है:

my_function(
  my_function(
    my_function(
      my_function(
        $accumulator,
        'a'),
      'b'),
    'c'),
  'd')

यदि आप लूप के संदर्भ में सोचना पसंद करते हैं, तो यह निम्न कार्य करने जैसा है (मैंने वास्तव में इसे एक कमबैक के रूप में उपयोग किया है जब array_reduce उपलब्ध था):

function array_reduce($array, $function, $accumulator) {
  foreach ($array as $element) {
    $accumulator = $function($accumulator, $element);
  }
  return $accumulator;
}

यह लूपिंग संस्करण यह स्पष्ट करता है कि मैंने तीसरे तर्क को 'संचायक' क्यों कहा है: हम इसका उपयोग प्रत्येक पुनरावृत्ति के माध्यम से परिणाम संचित करने के लिए कर सकते हैं।

तो ऐसा करने के लिए array_map और array_filter का क्या करना है? यह पता चला है कि वे दोनों एक विशेष प्रकार के array_reduce हैं। हम उन्हें इस तरह से लागू कर सकते हैं:

array_map($function, $array)    === array_reduce($array, $MAP,    array())
array_filter($array, $function) === array_reduce($array, $FILTER, array())

इस तथ्य को अनदेखा करें कि array_map और array_filter एक अलग क्रम में उनके तर्क लेते हैं; यह PHP का सिर्फ एक और उद्धरण है। महत्वपूर्ण बिंदु यह है कि जिन कार्यों को मैंने $ MAP और $ FILTER कहा है, को छोड़कर दाएँ-बाएँ एक समान है। तो, वे क्या दिखते हैं?

$MAP = function($accumulator, $element) {
  $accumulator[] = $function($element);
  return $accumulator;
};

$FILTER = function($accumulator, $element) {
  if ($function($element)) $accumulator[] = $element;
  return $accumulator;
};

जैसा कि आप देख सकते हैं, दोनों कार्य $ संचयकर्ता में लेते हैं और इसे फिर से लौटाते हैं। इन कार्यों में दो अंतर हैं:

  • $ MAP हमेशा $ संचायक के लिए अपील करेगा, लेकिन $ FILTER केवल तभी करेगा जब $ फ़ंक्शन ($ तत्व) TRUE होगा।
  • $ फिल्टर मूल तत्व को जोड़ता है, लेकिन $ MAP $ फ़ंक्शन ($ तत्व) को जोड़ता है।

ध्यान दें कि यह बेकार ट्रिविया से दूर है; हम अपने एल्गोरिदम को अधिक कुशल बनाने के लिए इसका उपयोग कर सकते हैं!

हम अक्सर इन दो उदाहरणों की तरह कोड देख सकते हैं:

// Transform the valid inputs
array_map('transform', array_filter($inputs, 'valid'))

// Get all numeric IDs
array_filter(array_map('get_id', $inputs), 'is_numeric')

लूप के बजाय array_map और array_filter का उपयोग करने से ये उदाहरण काफी अच्छे लगते हैं। हालांकि, यह बहुत अकुशल हो सकता है अगर $ निविष्टियाँ बड़ी हैं, क्योंकि पहली कॉल (नक्शा या फ़िल्टर) $ आदानों को पीछे छोड़ देगी और एक मध्यवर्ती सरणी का निर्माण करेगी। इस मध्यवर्ती सरणी को सीधे दूसरी कॉल में पारित किया जाता है, जो पूरी चीज़ को फिर से पार कर जाएगी, फिर मध्यवर्ती सरणी को कचरा एकत्र करने की आवश्यकता होगी।

हम इस मध्यवर्ती सरणी से इस तथ्य से छुटकारा पा सकते हैं कि array_map और array_filter दोनों array_reduce के उदाहरण हैं। उन्हें मिलाकर, हमें केवल प्रत्येक उदाहरण में एक बार $ निविष्टियों को पार करना होगा:

// Transform valid inputs
array_reduce($inputs,
             function($accumulator, $element) {
               if (valid($element)) $accumulator[] = transform($element);
               return $accumulator;
             },
             array())

// Get all numeric IDs
array_reduce($inputs,
             function($accumulator, $element) {
               $id = get_id($element);
               if (is_numeric($id)) $accumulator[] = $id;
               return $accumulator;
             },
             array())

नोट: ऊपर array_map और array_filter का मेरा कार्यान्वयन PHP के समान व्यवहार नहीं करेगा, क्योंकि मेरे array_map केवल एक समय में एक सरणी को संभाल सकते हैं और मेरे array_filter "डिफ़ॉल्ट" का उपयोग अपने डिफ़ॉल्ट $ फ़ंक्शन के रूप में नहीं करेंगे। इसके अलावा, न तो चाबियाँ संरक्षित करेगा।

उन्हें PHP की तरह व्यवहार करना मुश्किल नहीं है, लेकिन मुझे लगा कि इन जटिलताओं से स्पॉट को समझना मुश्किल हो जाएगा।


1

निम्नलिखित पुनरीक्षण अधिक स्पष्ट रूप से delineate PHP के array_filer (), array_map (), और array_walk () की तलाश में है, जो सभी कार्यात्मक प्रोग्रामिंग से उत्पन्न होते हैं:

array_filter () डेटा को फ़िल्टर करता है, जिसके परिणामस्वरूप पूर्व सरणी के केवल वांछित आइटम रखने वाले एक नए सरणी का निर्माण होता है:

<?php
$array = array(1, "apples",2, "oranges",3, "plums");

$filtered = array_filter( $array, "ctype_alpha");
var_dump($filtered);
?>

लाइव कोड यहां

सभी अंकीय मान $ सरणी से फ़िल्टर किए जाते हैं, केवल फलों के प्रकार के साथ $ फ़िल्टर किए जाते हैं।

array_map () भी एक नया सरणी बनाता है, लेकिन array_filter () के विपरीत परिणामी सरणी में इनपुट के प्रत्येक तत्व को फ़िल्टर किया गया है, लेकिन परिवर्तित मानों के कारण, प्रत्येक तत्व में कॉलबैक लागू करने के लिए निम्नानुसार है:

<?php

$nu = array_map( "strtoupper", $filtered);
var_dump($nu);
?>

लाइव कोड यहां

इस मामले में कोड अंतर्निहित strtoupper () का उपयोग करके कॉलबैक लागू होता है, लेकिन उपयोगकर्ता द्वारा परिभाषित फ़ंक्शन एक और व्यवहार्य विकल्प भी है। कॉलबैक फ़िल्टर किए गए $ के प्रत्येक आइटम पर लागू होता है और इस तरह $ nu को संलग्न करता है जिसके तत्वों में अपरकेस मान होते हैं।

अगले स्निपेट में, सरणी चलना () $ nu का पता लगाता है और प्रत्येक तत्व में परिवर्तन करता है जो संदर्भ ऑपरेटर '&' का दृश्य बनाता है। अतिरिक्त सरणी बनाए बिना परिवर्तन होते हैं। हर तत्व का मूल्य एक अधिक जानकारीपूर्ण स्ट्रिंग में जगह बदलता है जो इसकी कुंजी, श्रेणी और मूल्य को निर्दिष्ट करता है।

<?php

$f = function(&$item,$key,$prefix) {
    $item = "$key: $prefix: $item";
}; 
array_walk($nu, $f,"fruit");
var_dump($nu);    
?>    

देख डेमो

नोट: array_walk () के संबंध में कॉलबैक फ़ंक्शन दो पैरामीटर लेता है जो स्वचालित रूप से एक तत्व का मूल्य और इसकी कुंजी प्राप्त करेगा और उस क्रम में भी array_walk () द्वारा आमंत्रित किया गया है। ( यहां और देखें )।


1
ध्यान दें कि फ़ंक्शन $lambdaऔर $callbackमौजूदा कार्यों के एटा-विस्तार हैं, और इसलिए पूरी तरह से बेमानी हैं। आप अंतर्निहित फ़ंक्शन: ( $filtered = array_filter($array, 'ctype_alpha');और ) के नाम को पास करके समान परिणाम प्राप्त कर सकते हैं: और$nu = array_map('strtoupper', $filtered);
वारबो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.