अन्य उत्तर 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 की तरह व्यवहार करना मुश्किल नहीं है, लेकिन मुझे लगा कि इन जटिलताओं से स्पॉट को समझना मुश्किल हो जाएगा।