कुंजी सहित PHP का array_map


208

क्या ऐसा कुछ करने का एक तरीका है:

$test_array = array("first_key" => "first_value", 
                    "second_key" => "second_value");

var_dump(array_map(function($a, $b) { return "$a loves $b"; }, 
         array_keys($test_array), 
         array_values($test_array)));

लेकिन कॉल करने के बजाय array_keysऔर array_values, सीधे $test_arrayचर को पार करने के लिए ?

वांछित उत्पादन है:

array(2) {
  [0]=>
  string(27) "first_key loves first_value"
  [1]=>
  string(29) "second_key loves second_value"
}

यह भी देखें: stackoverflow.com/search?q=each_with_index यह सामान्य समस्या के लिए एक विषम दृष्टिकोण के लिए
dreftymac

जवाबों:


206

Array_map के साथ नहीं, क्योंकि यह कुंजियों को संभालता नहीं है।

array_walk करता है:

$test_array = array("first_key" => "first_value",
                    "second_key" => "second_value");
array_walk($test_array, function(&$a, $b) { $a = "$b loves $a"; });
var_dump($test_array);

// array(2) {
//   ["first_key"]=>
//   string(27) "first_key loves first_value"
//   ["second_key"]=>
//   string(29) "second_key loves second_value"
// }

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

आप एक ऐसा कार्य लिख सकते हैं जो यदि आप चाहते हैं तो अपने आप से ऊपर के बिंदुओं को ठीक करता है:

function mymapper($arrayparam, $valuecallback) {
  $resultarr = array();
  foreach ($arrayparam as $key => $value) {
    $resultarr[] = $valuecallback($key, $value);
  }
  return $resultarr;
}

$test_array = array("first_key" => "first_value",
                    "second_key" => "second_value");
$new_array = mymapper($test_array, function($a, $b) { return "$a loves $b"; });
var_dump($new_array);

// array(2) {
//   [0]=>
//   string(27) "first_key loves first_value"
//   [1]=>
//   string(29) "second_key loves second_value"
// }

सिवाय इसके कि इस मामले में, आप $a = "$b loves $a"ओपी के वांछित आउटपुट से मिलान करना चाहते हैं ।
cmbuckley

1
सही, परिवर्तित :) यह अच्छा है कि उन्होंने array_walk से array_map को कितना अलग बनाया है।
eis

अच्छा धन्यवाद। मूल सरणी को गड़बड़ाने से बचने के लिए, यहां मैंने आखिरकार क्या किया (नीचे मेरा उत्तर देखें)
जोस टॉमस टोचीनो

3
यह "फंक्शनल-प्रोग्रामिंग" नहीं है, क्योंकि array_walk()परिणामी सरणी वापस नहीं आती है, लेकिन इसके बजाय एक बूल है।
मॅई

@ हाँ, जैसे मैंने उत्तर में लिखा था - मान वापस करने के बजाय यह पैरामीटर बदलता है
eis

145

यह संभवतः सबसे छोटा और सबसे आसान कारण है:

$states = array('az' => 'Arizona', 'al' => 'Alabama');

array_map(function ($short, $long) {
    return array(
        'short' => $short,
        'long'  => $long
    );
}, array_keys($states), $states);

// produces:
array(
     array('short' => 'az', 'long' => 'Arizona'), 
     array('short' => 'al', 'long' => 'Alabama')
)

15
मुझे बस एहसास हुआ कि प्रश्न विशेष रूप से उपयोग नहीं करने के लिए कहा गया था array_keys()। हालांकि यह एक मूर्खतापूर्ण आवश्यकता की तरह लगता है।
केविन बील

3
सवाल ने array_keys () का उपयोग करके एक समाधान प्रदान किया, यह वर्तमान समाधान पर कोई जवाब नहीं है (उदाहरण के लिए, कम फ़ंक्शन कॉलिंग) कोई जवाब देने के लिए मूर्खतापूर्ण होगा।
चिनोटो वोक्रो

मूल प्रश्न का उत्तर NO है, और यह सबसे उपयुक्त समाधान है।
usoban 14

65

यहाँ मेरा बहुत ही सरल, PHP 5.5-संगत समाधान है:

function array_map_assoc(callable $f, array $a) {
    return array_column(array_map($f, array_keys($a), $a), 1, 0);
}

आपके द्वारा आपूर्ति की जाने वाली कॉल करने योग्य सामग्री को दो मानों के साथ एक सरणी को वापस करना चाहिए, अर्थात return [key, value]array_mapइसलिए आंतरिक कॉल सरणियों की एक सरणी का उत्पादन करता है। यह तब एकल-आयाम सरणी में वापस परिवर्तित हो जाता है array_column

प्रयोग

$ordinals = [
    'first' => '1st',
    'second' => '2nd',
    'third' => '3rd',
];

$func = function ($k, $v) {
    return ['new ' . $k, 'new ' . $v];
};

var_dump(array_map_assoc($func, $ordinals));

उत्पादन

array(3) {
  ["new first"]=>
  string(7) "new 1st"
  ["new second"]=>
  string(7) "new 2nd"
  ["new third"]=>
  string(7) "new 3rd"
}

आंशिक आवेदन

मामले में आपको विभिन्न सरणियों के साथ कई बार फ़ंक्शन का उपयोग करने की आवश्यकता होती है, लेकिन एक ही मैपिंग फ़ंक्शन, आप आंशिक फ़ंक्शन अनुप्रयोग (' करी ' से संबंधित ) नामक कुछ कर सकते हैं , जो आपको केवल आह्वान पर डेटा सरणी में पास करने की अनुमति देता है:

function array_map_assoc_partial(callable $f) {
    return function (array $a) use ($f) {
        return array_column(array_map($f, array_keys($a), $a), 1, 0);
    };
}

...
$my_mapping = array_map_assoc_partial($func);
var_dump($my_mapping($ordinals));

जो समान आउटपुट देता है, दिया $funcऔर $ordinalsपहले जैसा है।

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


विकल्प

निम्नलिखित उपरोक्त का एक प्रकार है, जो कुछ के लिए अधिक तार्किक साबित हो सकता है, लेकिन इसके लिए PHP 5.6 की आवश्यकता होती है:

function array_map_assoc(callable $f, array $a) {
    return array_merge(...array_map($f, array_keys($a), $a));
}

इस संस्करण में, आपका दिया गया फ़ंक्शन (जिस पर डेटा सरणी मैप की गई है) इसके बजाय एक पंक्ति, यानी के साथ एक सहयोगी सरणी वापस करना चाहिए return [key => value]। तब कॉल करने योग्य मैपिंग का परिणाम बस अनपैक किया गया और पास किया गया array_merge। पहले की तरह, डुप्लिकेट कुंजी को वापस करने के परिणामस्वरूप बाद के मूल्यों की जीत होगी।

nb Alex83690 ने एक टिप्पणी में कहा है कि array_replaceयहाँ के उपयोग से array_mergeपूर्णांक कुंजियाँ संरक्षित होंगी। array_replaceइनपुट सरणी को संशोधित नहीं करता है, इसलिए कार्यात्मक कोड के लिए सुरक्षित है।

यदि आप PHP 5.3 से 5.5 पर हैं, तो निम्नलिखित बराबर है। यह array_reduceद्विआधारी +सरणी ऑपरेटर का उपयोग करता है और परिणामी दो-आयामी सरणी को एक-आयामी सरणी में परिवर्तित करने के लिए कुंजी को संरक्षित करता है:

function array_map_assoc(callable $f, array $a) {
    return array_reduce(array_map($f, array_keys($a), $a), function (array $acc, array $a) {
        return $acc + $a;
    }, []);
}

प्रयोग

इस प्रकार इन दोनों प्रकारों का उपयोग किया जाएगा:

$ordinals = [
    'first' => '1st',
    'second' => '2nd',
    'third' => '3rd',
];

$func = function ($k, $v) {
    return ['new ' . $k => 'new ' . $v];
};

var_dump(array_map_assoc($func, $ordinals));

नोट =>के बदले ,में $func

आउटपुट पहले जैसा ही है, और प्रत्येक को पहले की तरह ही आंशिक रूप से लागू किया जा सकता है।


 सारांश

मूल प्रश्न का लक्ष्य कॉल के आह्वान को अधिक से अधिक जटिल कार्य करने की कीमत पर यथासंभव सरल बनाना है; विशेष रूप से, डेटा सरणी को एक तर्क के रूप में पारित करने की क्षमता है, बिना कुंजियों और मूल्यों के विभाजन के। इस उत्तर की शुरुआत में दिए गए फ़ंक्शन का उपयोग करना:

$test_array = ["first_key" => "first_value",
               "second_key" => "second_value"];

$array_map_assoc = function (callable $f, array $a) {
    return array_column(array_map($f, array_keys($a), $a), 1, 0);
};

$f = function ($key, $value) {
    return [$key, $key . ' loves ' . $value];
};

var_dump(array_values($array_map_assoc($f, $test_array)));

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

$test_array = ["first_key" => "first_value",
               "second_key" => "second_value"];

$array_map_assoc = function (callable $f, array $a) {
    return array_map($f, array_keys($a), $a);
};

$f = function ($key, $value) {
    return $key . ' loves ' . $value;
};

var_dump($array_map_assoc($f, $test_array));

तो जवाब नहीं है , आप कॉल करने से बच सकते हैं array_keys, लेकिन आप उस स्थान को अलग कर सकते हैं जहां array_keysएक उच्च-क्रम फ़ंक्शन में बुलाया जाता है, जो काफी अच्छा हो सकता है।


7
ऐसा लगता है कि सही उत्तर के रूप में चिह्नित किया जाना चाहिए।
eddiewould

6
धन्यवाद @eddiewould, लेकिन मुझे लगभग ed late साल बहुत देर हो गई है :) मैं यहाँ एक समाधान की तलाश में आया था, मुझे कोई पसंद नहीं आया, इसलिए मैं अपने साथ आया।
निकोलस शैंक्स

1
मैं उस आदमी हो जाएगा PHP 5.3 को अब इस उत्तर की तारीख की आवश्यकता नहीं होनी चाहिए । IMHO।
Erutan409

1
आपका पहला वैकल्पिक समाधान अमान्य है। आप बदलना होगा array_mergeद्वारा array_replaceकुंजी कि पूर्णांकों होगा बनाए रखने के लिए।
एलेक्स .३६

1
@ Alex83690 धन्यवाद! हालांकि मैं कहूंगा कि "अमान्य 'थोड़ा भ्रामक है - यदि आपके पास कोई पूर्णांक कुंजी नहीं है (जैसा कि मेरे स्वयं के मामले में सच था) - यह ठीक है।
निकोलस शैंक्स

20

PHP5.3 या बाद के साथ:

$test_array = array("first_key" => "first_value", 
                    "second_key" => "second_value");

var_dump(
    array_map(
        function($key) use ($test_array) { return "$key loves ${test_array[$key]}"; },
        array_keys($test_array)
    )
);

1
मुझे लगता है कि आवश्यकता थी "कॉल करने के बजाय array_keys और array_values, सीधे $ test_array वैरिएबल पास करने के लिए", क्या इसे array_keys के बिना उपयोग किया जा सकता है?
eis

4

इस तरह मैंने इसे अपने प्रोजेक्ट में लागू किया है।

function array_map_associative(callable $callback, $array) {
    /* map original array keys, and call $callable with $key and value of $key from original array. */
    return array_map(function($key) use ($callback, $array){
        return $callback($key, $array[$key]);
    }, array_keys($array));
}

बहुत साफ है, और मूल सरणी में परिवर्तन नहीं करता है!
राफेल कैंडेलिएरे

4

इधर देखो! एक तुच्छ समाधान है!

function array_map2(callable $f, array $a)
{
    return array_map($f, array_keys($a), $a);
}

जैसा कि प्रश्न में कहा गया है, array_map पहले से ही वास्तव में कार्यक्षमता की आवश्यकता है । अन्य उत्तर यहां की बातों को गंभीरता से समझते हैं: array_walkयह क्रियाशील नहीं है।

प्रयोग

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

$test_array = array("first_key" => "first_value", 
                    "second_key" => "second_value");

var_dump(array_map2(function($a, $b) { return "$a loves $b"; }, $test_array));

अन्य उत्तर चीजों को ओवरकम्प्लीट करते हैं क्योंकि निर्दिष्ट प्रश्न का qrrqy_keys()उपयोग #reasons के लिए नहीं किया जाना चाहिए
ब्रैड केंट

2

"मैनुअल लूप" से मेरा मतलब एक कस्टम फ़ंक्शन लिखना है जो उपयोग करता है foreach। यह एक नया सरणी देता है जैसे array_mapकि फ़ंक्शन का दायरा $arrayकॉपी होने का कारण बनता है - संदर्भ नहीं:

function map($array, callable $fn) {
  foreach ($array as $k => &$v) $v = call_user_func($fn, $k, $v);
  return $array;
}

आपका तकनीक का उपयोग कर array_mapके साथ array_keysहालांकि वास्तव में सरल लगता है और क्योंकि आप उपयोग कर सकते हैं और अधिक शक्तिशाली है nullएक कॉलबैक के रूप में कुंजी-मान जोड़ों वापस जाने के लिए:

function map($array, callable $fn = null) {
  return array_map($fn, array_keys($array), $array);
}

संदर्भ के साथ लूपिंग सरणी, डरावना चीजें होने का
जेंज़ें00

यह डरावना नहीं है, इसका मतलब है कि आप भूल गए unset( $value )क्योंकि यह अभी भी परिभाषित दायरे में मौजूद है।
अजीज पुन्जानी

@azis, लेख के संदर्भ में, चंचलता के बारे में मजाक कर रहा था। यदि आप परेशान करना भूल जाते हैं तो यह अप्रत्याशित प्रभाव पैदा करेगा।
jenenz00

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

@ janenz00 स्पष्टीकरण के लिए संपादित उत्तर देखें। मेरा मतलब साफ चर दायरे में लूपिंग से है।
राणीव १२'१४

1

ईस के उत्तर के आधार पर , यहां मैंने मूल सरणी को गड़बड़ाने से बचने के लिए आखिरकार क्या किया:

$test_array = array("first_key" => "first_value",
                    "second_key" => "second_value");

$result_array = array();
array_walk($test_array, 
           function($a, $b) use (&$result_array) 
           { $result_array[] = "$b loves $a"; }, 
           $result_array);
var_dump($result_array);

2
यह सरणी मूल्यों और कुंजियों को सीधे array_map पर भेजने से आसान क्यों है? यह धीमा और अधिक जटिल है, मुझे फायदा नहीं दिख रहा है।
एरियल

1
@ एरियल क्या आप इस दावे का समर्थन कर सकते हैं कि यह बड़ी संख्या के साथ भी धीमी होगी? इसे केवल एक बार सरणी को पुनरावृत्त करने की आवश्यकता है, इसलिए मुझे लगता है कि बड़े ओ नोटेशन में तेजी से परिमाण होना चाहिए। मैं हालांकि जटिलता के बारे में सहमत हूं।
eis

@eis यह धीमा है क्योंकि यह परिणामी सरणी को PHP में एक समय में बना रहा है, बजाय C. में मालिश करने के। यह array_keys कॉल से बचता है, हालांकि (हालांकि यह C में तेज है)। बेंचमार्क यह - देखें कि कौन सा तेज है, मैं वास्तव में निश्चित नहीं हूं, लेकिन आमतौर पर अधिक कोड = धीमा कोड। जटिलता में हालांकि यह निश्चित रूप से बदतर है, और यह ज्यादातर समय की गति से अधिक महत्वपूर्ण है।
एरियल

1
आपको तीसरे आर्ग को भेजने की आवश्यकता नहीं है array_walkक्योंकि आप इसे क्लोजर में संदर्भित नहीं कर रहे हैं।
स्टीवन लू

1

मैंने इस समारोह को eis के उत्तर पर आधारित बनाया है :

function array_map_($callback, $arr) {
    if (!is_callable($callback))
        return $arr;

    $result = array_walk($arr, function(&$value, $key) use ($callback) {
        $value = call_user_func($callback, $key, $value);
    });

    if (!$result)
        return false;

    return $arr;
}

उदाहरण:

$test_array = array("first_key" => "first_value", 
                "second_key" => "second_value");

var_dump(array_map_(function($key, $value){
    return $key . " loves " . $value;
}, $arr));

आउटपुट:

array (
  'first_key' => 'first_key loves first_value,
  'second_key' => 'second_key loves second_value',
)

बेशक, आप array_valuesओपी को जो चाहते हैं उसे वापस करने के लिए उपयोग कर सकते हैं ।

array_values(array_map_(function($key, $value){
    return $key . " loves " . $value;
}, $test_array))

@KevinBeal मैं अपने काम में इस फ़ंक्शन का बहुत उपयोग करता हूं। क्या आप बता सकते हैं कि त्रुटियाँ कहाँ हैं?
जूलियो वेदोवत्तो

2
सबसे पहले, जैसा कि यह खड़ा है कोड एक चेक को याद कर रहा है जो कि $arrप्रकार सरणी का है, हालांकि यदि आप अपने तर्क टाइप करते हैं callableऔर arrayआप चेक को छोड़ सकते हैं is_callable। इसके बाद, आप $ मान के लिए एक असाइनमेंट बनाते हैं जो तब अप्रयुक्त है। आपको सिर्फ रिटर्न वैल्यू को नजरअंदाज करना चाहिए। तीसरा, कॉलबैक में एक अपवाद को फेंकना बेहतर होगा कि वह झूठे वापस आए। आप तब या तो हमेशा एक वैध मान लौटाते हैं या हमेशा फेंक देते हैं।
निकोलस शैंक्स

1

YaLinqo पुस्तकालय * इस तरह के कार्य के लिए अच्छी तरह से अनुकूल है। यह .NET से LINQ का एक पोर्ट है जो सभी कॉलबैक में मान और कुंजियों का पूर्ण समर्थन करता है और SQL जैसा दिखता है। उदाहरण के लिए:

$mapped_array = from($test_array)
    ->select(function ($v, $k) { return "$k loves $v"; })
    ->toArray();

या केवल:

$mapped_iterator = from($test_array)->select('"$k loves $v"');

यहां, '"$k loves $v"'पूर्ण बंद सिंटैक्स के लिए एक शॉर्टकट है जो इस लाइब्रेरी का समर्थन करता है। toArray()अंत में वैकल्पिक है। विधि श्रृंखला एक पुनरावृत्ति देता है, इसलिए यदि परिणाम का उपयोग करने पर पुनरावृत्त होना चाहिए foreach, तो toArrayकॉल को हटाया जा सकता है।

* मेरे द्वारा विकसित


1

मैं ऐसा कुछ करूँगा:

<?php

/**
 * array_map_kv()
 *   An array mapping function to map with both keys and values.
 *
 * @param $callback callable
 *   A callback function($key, $value) for mapping values.
 * @param $array array
 *   An array for mapping.
 */
function array_map_kv(callable $callback, array $array) {
  return array_map(
    function ($key) use ($callback, $array) {
      return $callback($key, $array[$key]); // $callback($key, $value)
    },
    array_keys($array)
  );
}

// use it
var_dump(array_map_kv(function ($key, $value) {
  return "{$key} loves {$value}";
}, array(
  "first_key" => "first_value",
  "second_key" => "second_value",
)));

?>

परिणाम:

array(2) {
  [0]=>
  string(27) "first_key loves first_value"
  [1]=>
  string(29) "second_key loves second_value"
}

1

मैं अभी तक 5.6 या बाद के संस्करण का उपयोग करके समस्या का एक और समाधान जोड़ूंगा। नहीं पता है कि यह पहले से ही महान समाधान (शायद नहीं) से अधिक कुशल है, लेकिन मेरे लिए यह सिर्फ पढ़ने के लिए सरल है:

$myArray = [
    "key0" => 0,
    "key1" => 1,
    "key2" => 2
];

array_combine(
    array_keys($myArray),
    array_map(
        function ($intVal) {
            return strval($intVal);
        },
        $myArray
    )
);

strval()में एक उदाहरण समारोह के रूप में उपयोग करना array_map, यह उत्पन्न करेगा:

array(3) {
  ["key0"]=>
  string(1) "0"
  ["key1"]=>
  string(1) "1"
  ["key2"]=>
  string(1) "2"
}

उम्मीद है कि मैं केवल एक ही व्यक्ति नहीं हूँ जो इस सरल को समझ लेता है। चाबियों का एक समूह और मूल्यों की array_combineएक key => valueसरणी से एक सरणी बनाता है , बाकी बहुत आत्म व्याख्यात्मक है।


1

आप इस सरणी लाइब्रेरी से मानचित्र विधि का उपयोग कर सकते हैं ताकि आप जो चाहें आसानी से प्राप्त कर सकें:

Arr::map($test_array, function($a, $b) { return "$a loves $b"; });

यह भी कुंजियों को संरक्षित करता है और नई सरणी देता है, अपनी आवश्यकताओं को पूरा करने के लिए कुछ अलग तरीकों का उल्लेख नहीं करता है।



0

मैं हमेशा सरणी मानचित्र के जावास्क्रिप्ट संस्करण को पसंद करता हूं। इसका सबसे सरल संस्करण होगा:

/**
 * @param  array    $array
 * @param  callable $callback
 * @return array
 */
function arrayMap(array $array, callable $callback)
{
    $newArray = [];

    foreach( $array as $key => $value )
    {
        $newArray[] = call_user_func($callback, $value, $key, $array);
    }

    return $newArray;
}

तो अब आप इसे केवल कॉलबैक फ़ंक्शन पास कर सकते हैं कि मूल्यों का निर्माण कैसे करें।

$testArray = [
    "first_key" => "first_value", 
    "second_key" => "second_value"
];

var_dump(
    arrayMap($testArray, function($value, $key) {
        return $key . ' loves ' . $value;
    });
);

यह किसी भी समारोह आप लिखने के लिए पिछले तर्क के रूप में डेटा के लिए अधिक उपयोगी है आप तो एक नया कार्य बनाने के रूप में कर सकते हैं कि ठंडा करने में कुछ विशिष्ट कॉलबैक (व्यवहार) - यानी आप समारोह रचना मिलती है: h(g(f($data)))लागू होता है f, तो g, तो hकरने के लिए अपने डेटा। यह आमतौर पर कार्यात्मक प्रोग्रामिंग में अधिक बहुमुखी माना जाता है, जिसमें एक फ़ंक्शन है जो गोताखोरों के डेटा पर एक ही ऑपरेशन करता है, एक फ़ंक्शन के लिए जो एक निश्चित डेटा सेट पर गोताखोरों के कार्यों को लागू करता है।
निकोलस शैंक्स

आपके उदाहरण में आपके पास फ़ंक्शन के लिए केवल 1 तर्क है। मुझे डेटा को पहले तर्क के रूप में रखना आसान लगता है, जैसे कि array_filter, array_reduce और सरणी फ़ंक्शंस जावास्क्रिप्ट में।
ब्लाबलाब्ला

यही मेरा सवाल है! अंतिम डेटा को पास करके, यह आपको फ़ंक्शन को क्यूर करने की अनुमति देता है (एक नया फ़ंक्शन बनाएं जो विशिष्ट ऑपरेशन के साथ लूपिंग को जोड़ता है) और नए फ़ंक्शन को एकल पैरामीटर के साथ कॉल करके डेटा पर लागू होता है । इस प्रिंसिपल को मैं इस उत्तर से बेहतर समझा सकता हूँ: इस जवाब में: stackoverflow.com/a/5863222
निकोलस शेक्स

क्या PHP जैसी भाषा में कंपोज़ फ़ंक्शन का उपयोग करना इस समस्या का बेहतर समाधान नहीं है?
ब्लाबलाब्ला

1
यह एक वैकल्पिक विकल्प है, लेकिन इसके लिए एफपी में अधिक निवेश की आवश्यकता है, उदाहरण के लिए: github.com/nickshanks/fp-php-talk/blob/master/lib.php#L24 या यह: github.com/nickshanks/php-fp/blob /master/src/fp.php#L62
निकोलस शंक

0

कुंजी को संरक्षित करने के साथ ऐसा करने का दूसरा तरीका:

$test_array = [
    "first_key"     => "first_value",
    "second_key"    => "second_value"
];

$f = function($ar) {
    return array_map(
        function($key, $val) {
            return "{$key} - {$val}";
        },
        array_keys($ar),
        $ar
    );
};

#-- WITHOUT preserving keys
$res = $f($test_array);

#-- WITH preserving keys
$res = array_combine(
    array_keys($test_array),
    $f($test_array)
);

-2

मुझे लगता है कि यह स्पष्ट जवाब याद आ रहा है:

function array_map_assoc(){
    if(func_num_args() < 2) throw new \BadFuncionCallException('Missing parameters');

    $args = func_get_args();
    $callback = $args[0];

    if(!is_callable($callback)) throw new \InvalidArgumentException('First parameter musst be callable');

    $arrays = array_slice($args, 1);

    array_walk($arrays, function(&$a){
        $a = (array)$a;
        reset($a);
    });

    $results = array();
    $max_length = max(array_map('count', $arrays));

    $arrays = array_map(function($pole) use ($max_length){
        return array_pad($pole, $max_length, null);
    }, $arrays);

    for($i=0; $i < $max_length; $i++){
        $elements = array();
        foreach($arrays as &$v){
            $elements[] = each($v);
        }
        unset($v);

        $out = call_user_func_array($callback, $elements);

        if($out === null) continue;

        $val = isset($out[1]) ? $out[1] : null;

        if(isset($out[0])){
            $results[$out[0]] = $val;
        }else{
            $results[] = $val;
        }
    }

    return $results;
}

बिल्कुल array_map की तरह काम करता है। लगभग।

वास्तव में, यह शुद्ध नहीं है mapक्योंकि आप इसे अन्य भाषाओं से जानते हैं। Php बहुत अजीब है, इसलिए इसके लिए कुछ बहुत ही अजीब उपयोगकर्ता कार्यों की आवश्यकता होती है, क्योंकि हम अपने ठीक से टूटे हुए को अनब्रेक नहीं करना चाहते हैंworse is better दृष्टिकोण ।

वास्तव में, यह वास्तव mapमें बिल्कुल नहीं है। फिर भी, यह अभी भी बहुत उपयोगी है।

  • Array_map से पहला स्पष्ट अंतर यह है कि कॉलबैक each()अकेले मूल्य के बजाय हर इनपुट सरणी से आउटपुट लेता है । आप अभी भी एक बार में अधिक सरणियों के माध्यम से पुनरावृति कर सकते हैं।

  • दूसरा अंतर यह है कि कॉलबैक से वापस आने के बाद कुंजी को किस तरह से हैंडल किया जाता है; कॉलबैक फ़ंक्शन से वापसी मान होना चाहिए array('new_key', 'new_value')। कुंजी को बदला जा सकता है और बदल दिया जा सकता है, वही कुंजी पिछले मान को अधिलेखित करने का कारण भी बन सकती है, यदि वही कुंजी वापस कर दी गई हो। यह सामान्य mapव्यवहार नहीं है, फिर भी यह आपको कुंजियों को फिर से लिखने की अनुमति देता है।

  • तीसरा अजीब बात है, अगर आप को छोड़ देते हैं है keyवापसी मान में (या तो द्वारा array(1 => 'value')या array(null, 'value')), नई कुंजी, आवंटित करने के लिए के रूप में यदि जा रहा है $array[] = $valueइस्तेमाल किया गया था। यही कारण है कि नहीं है mapके सामान्य व्यवहार या तो, फिर भी यह काम कभी कभी आता है, मुझे लगता है।

  • चौथा अजीब बात है, अगर कॉलबैक फ़ंक्शन एक मान, या रिटर्न नहीं देता है null, तो वर्तमान कुंजी और मूल्यों का पूरा सेट आउटपुट से छोड़ दिया जाता है, यह बस छोड़ दिया जाता है। यह सुविधा पूरी तरह से एक प्रकार की mapपी है, फिर भी यह इस तरह के फ़ंक्शन के लिए उत्कृष्ट स्टंट को दोगुना array_filter_assocकर देगा।

  • यदि आप कॉलबैक की वापसी में दूसरे तत्व ( 1 => ...) ( मान भाग) को छोड़ देते हैं, तो nullइसका उपयोग वास्तविक मूल्य के बजाय किया जाता है।

  • चाबियाँ 0और 1कॉलबैक के रिटर्न को छोड़कर किसी भी अन्य तत्वों को अनदेखा किया जाता है।

  • और अंत में, यदि लैम्ब्डा nullया सरणी को छोड़कर किसी भी मूल्य को लौटाता है, तो यह माना जाता है कि कुंजी और मूल्य दोनों को छोड़ दिया गया था, इसलिए:

    1. तत्व के लिए नई कुंजी असाइन की गई है
    2. null इसका उपयोग मूल्य के रूप में किया जाता है
चेतावनी:
ध्यान रखें, कि यह अंतिम विशेषता पिछली विशेषताओं का एक अवशेष है और यह संभवतः पूरी तरह से बेकार है। इस सुविधा पर भरोसा करना बहुत हतोत्साहित करता है, क्योंकि यह सुविधा बेतरतीब ढंग से बदली जा रही है और आगामी रिलीज़ में अप्रत्याशित रूप से बदल दिया है।

नोट: इसके
विपरीत array_map, array_map_assocपहले कॉलबैक पैरामीटर के अपवाद के साथ पारित किए गए सभी गैर-सरणी पैरामीटर, चुपचाप सरणियों के लिए डाले जाते हैं।

उदाहरण:
// TODO: examples, anyone?

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.