कैसे एक बहुआयामी सरणी को समतल करने के लिए?


259

क्या यह संभव है, PHP में, पुनरावृत्ति या संदर्भों का उपयोग किए बिना एक (द्वि / बहु) आयामी सरणी को समतल करने के लिए?

मुझे केवल मूल्यों में दिलचस्पी है इसलिए कुंजियों को अनदेखा किया जा सकता है, मैं array_map()और की लाइनों में सोच रहा हूं array_values()


17
पुनरावृत्ति से क्यों बचें?
जोरेनब

5
Dupe (ज्यादातर) stackoverflow.com/questions/526556/…
cletus

4
आप पुनरावृत्ति के बिना एक मनमाने ढंग से गहरी सरणियों के सभी तत्वों के साथ कुछ भी नहीं कर सकते हैं (आप इसे पुनरावृत्ति के रूप में प्रच्छन्न कर सकते हैं, लेकिन आलू, पोटाहो।) यदि आप सिर्फ अपने आप को पुनरावृत्ति हैंडलिंग कोड लिखने से बचना चाहते हैं, तो dd2.php.net/ का उपयोग करें । मैनुअल / en / function.array-walk-recursive.php एक कॉलबैक के साथ जो तत्व को उपलब्ध सरणी में जोड़ता है (वैश्विक उपयोग करें, उपयोगकर्ताडेटा पैरामीटर, इसे सभी को एक कक्षा में रखें और इसे $ का संदर्भ दें, आदि)
माइकल मैडसेन

@JorenB: मैं देखना चाहता हूं कि एक कार्यान्वयन को बढ़ाया जा सकता है।
एलिक्स एक्सल

Nspl से समतल समारोह पर एक नजर है । आप इसके साथ एक गहराई भी निर्दिष्ट कर सकते हैं।
इहोर बर्लाचेंको

जवाबों:


276

आप पुनरावर्ती को "छिपाने" के लिए मानक PHP लाइब्रेरी (एसपीएल) का उपयोग कर सकते हैं ।

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($a));
foreach($it as $v) {
  echo $v, " ";
}

प्रिंट

1 2 3 4 5 6 7 8 9 

351
क्या मैं केवल यही सोचता हूं कि 'RecursiveIteratorIterator' एक मूर्खतापूर्ण नाम है?
nilamo

45
यह "आकर्षक" की तुलना में अधिक "तार्किक" है। सब कुछ एक शानदार नाम नहीं हो सकता है जैसे JOGL, Knol या Azure :-)
VolkerK

7
यह बच्चों के रूप में खाली सरणियों के लिए काम नहीं करेगा। उन्हें माता-पिता के रूप में लौटाया जाएगा।
हैकर

45
iterator_to_array($it, false)फॉर्च की आवश्यकता से बचा जाता है।
एलिक्स एक्सल

3
दूसरों ने जो प्रस्तुत किया है, उस पर निर्माण करते हुए, मैं इस छोटे सहायक को तैयार करने में सक्षम था: function flatten($arr){ $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)); return iterator_to_array($it, true); }आशा है कि यह दूसरों की मदद करता है।
माइक एस।

295

PHP 5.3 के रूप में सबसे छोटा समाधान array_walk_recursive()नए क्लोजर सिंटैक्स के साथ लगता है :

function flatten(array $array) {
    $return = array();
    array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
    return $return;
}

33
यदि आप चाबियां चाहते हैं, तो फलैटेन (सरणी $ सरणी) {$ रिटर्न = सरणी (); array_walk_recursive ($ सरणी, फ़ंक्शन ($ a, $ b) उपयोग (और $ वापसी) {$ वापसी [$ b] = $ a;}); $ वापसी; }
ब्रेंडन-वान-हेज़ेन

क्या आप इसे php 5.2 के साथ उपयोग करने के लिए फिर से लिख सकते हैं?
एलेक्स

2
@ आप दुर्भाग्य useसे इस काम को करने के लिए वाक्यविन्यास की जरूरत है array_walk_recursiveक्योंकि यह $userdataसंदर्भ द्वारा वैकल्पिक पैरामीटर को स्वीकार नहीं करेगा
टिम Seguine

1
इस तरह के Arrays के लिए ठीक काम की तरह देखो -> ideone.com/DsmApP लेकिन ऐसे लोगों के लिए नहीं -> ideone.com/5Kltva या क्या यह मैं हूं?
सेबेस्टियन पिस्कोर्स्की

2
@ सेबैस्टियन पिस्कोर्स्की यह इसलिए है क्योंकि आपके मूल्यों को कुंजी की तरह माना जा रहा है, इसलिए जैसे ही आप किसी सरणी में अपनी कुंजी => वैल्यू पेयर का परिचय देते हैं, पहली इंडेक्स स्थिति में आपके एरे वैल्यू को बिना मान वाले कुंजी की तरह माना जाता है, और क्योंकि चाबियाँ हैं अद्वितीय होने के लिए, जहाँ दो कुंजियाँ मेल खाती हैं, आपके मान उसी कुंजी में जुड़ जाते हैं। एक सरल समाधान यह होगा कि पहले सरणी को क्रमबद्ध किया जाए। यह PHP में निहित व्यवहार है।
मार्टन शट

92

2 आयामी सरणी के लिए समाधान

कृपया इसे आज़माएँ:

$array  = your array

$result = call_user_func_array('array_merge', $array);

echo "<pre>";
print_r($result);

EDIT: 21-अगस्त -13

यहाँ समाधान है जो बहु-आयामी सरणी के लिए काम करता है:

function array_flatten($array) {
    $return = array();
    foreach ($array as $key => $value) {
        if (is_array($value)){
            $return = array_merge($return, array_flatten($value));
        } else {
            $return[$key] = $value;
        }
    }

    return $return;
}

$array  = Your array

$result = array_flatten($array);

echo "<pre>";
print_r($result);

Ref: http://php.net/manual/en/function.call-user-func-array.php


धन्यवाद, पहले एक ने एक सरणी पर काम किया जो मुझे पीडीओ से मिल रहा था जहां अन्य समाधान नहीं थे।
JAL

7
यह एक खराब रणनीति है। call_user_func_array('array_merge', [])(खाली सरणी पर ध्यान दें) अशक्त देता है और एक php चेतावनी त्रुटि चलाता है। यदि आप इस तथ्य के बारे में जानते हैं कि यह आपके लिए खाली नहीं होगा, तो यह एक चालाक समाधान है, लेकिन यह एक आम धारणा नहीं है जो कई कर सकते हैं।
बकरी

ओपी ने विशेष रूप से गैर-पुनरावर्ती समाधानों के लिए कहा।
27lektra

वाह, शांत 2d फ्लैट! लेकिन नोटिस का उपयोग करने से रोकने के लिए$result = $array ?call_user_func_array('array_merge', $array) : [];
अलेक्जेंडर गोंचारोव

कूल ब्रू, लेकिन क्या आपके पास मौका नहीं है एक काउंटर-फ़ंक्शन सरणी-डिफ्लैटन है?
FantomX1

64

PHP 5.6 और इसके array_mergeबाद के संस्करण में आप ...ऑपरेटर के साथ बाहरी सरणी को अनपैक करने के बाद दो आयामी सरणियों को समतल कर सकते हैं । कोड सरल और स्पष्ट है।

array_merge(...$a);

यह सहयोगी सरणियों के संग्रह के साथ भी काम करता है।

$a = [[10, 20], [30, 40]];
$b = [["x" => "X", "y" => "Y"], ["p" => "P", "q" => "Q"]];

print_r(array_merge(...$a));
print_r(array_merge(...$b));

Array
(
    [0] => 10
    [1] => 20
    [2] => 30
    [3] => 40
)
Array
(
    [x] => X
    [y] => Y
    [p] => P
    [q] => Q
)

लेकिन यह काम नहीं करता है जब बाहरी सरणी में गैर-संख्यात्मक कुंजी होती है। उस स्थिति में, आपको array_valuesपहले कॉल करना होगा ।

$c = ["a" => ["x" => "X", "y" => "Y"], "b" => ["p" => "P", "q" => "Q"]];
print_r(array_merge(...array_values($c)));

Array
(
    [x] => X
    [y] => Y
    [p] => P
    [q] => Q
)

अपडेट: @MohamedGharib द्वारा टिप्पणी के आधार पर

यदि बाहरी सरणी खाली है, तो यह एक त्रुटि है, क्योंकि array_mergeशून्य तर्क के साथ कहा जाएगा। पहले तर्क के रूप में एक खाली सरणी जोड़कर इसे टाला जा सकता है।

array_merge([], ...$a);

1
यह तभी काम करता है जब सरणी का प्रत्येक तत्व एक सरणी है। यदि सरणी में मिश्रित प्रकार होते हैं, जैसे कि स्केलर, तो एक त्रुटि होगी।
ओथियस

@Otheus ऐसा इसलिए है क्योंकि उपरोक्त समाधान पुनरावृत्ति का उपयोग नहीं करता है। जैसा कि आपने कहा, इसके लिए एक सारणी की आवश्यकता होती है। लेकिन प्लस साइड पर, यह बहुत तेज़ होना चाहिए कि अन्य विधियां, क्योंकि इसमें फ़ंक्शन कॉल का अतिरिक्त ओवरहेड नहीं है।
जॉयस बाबू

2
यदि कोई बाहरी सरणी खाली है, तो एक त्रुटि को फेंक देगा, यदि खाली सरणी के साथ जोड़ दिया जा सकता है तो इससे बचा जा सकता हैarray_merge([], ...$a);
मोहम्मद ग़रीब

@ मोहम्मद गरिब अच्छा कैच।
जायसी बाबू

यदि साहचर्य सरणियों का उपयोग करके आप इस समाधान को जांच सकते हैं stackoverflow.com/questions/40663687/…
एलेक्स

24

डब्ल्यू / ओ पुनरावृत्ति (जैसा आपने पूछा है) को समतल करने के लिए, आप एक स्टैक का उपयोग कर सकते हैं । स्वाभाविक रूप से आप इसे इस तरह के एक समारोह में डाल सकते हैं array_flatten। निम्नलिखित एक संस्करण है जो w / o कीज़ को काम करता है:।

function array_flatten(array $array)
{
    $flat = array(); // initialize return array
    $stack = array_values($array); // initialize stack
    while($stack) // process stack until done
    {
        $value = array_shift($stack);
        if (is_array($value)) // a value to further process
        {
            $stack = array_merge(array_values($value), $stack);
        }
        else // a value to take
        {
           $flat[] = $value;
        }
    }
    return $flat;
}

तत्वों को उनके क्रम में संसाधित किया जाता है। क्योंकि सबलेमेंट्स को स्टैक के ऊपर ले जाया जाएगा, उन्हें आगे संसाधित किया जाएगा।

कुंजी को ध्यान में रखना संभव है, हालांकि, स्टैक को संभालने के लिए आपको एक अलग रणनीति की आवश्यकता होगी। इसकी आवश्यकता है क्योंकि आपको उप-सरणियों में संभावित डुप्लिकेट कुंजियों से निपटने की आवश्यकता है। संबंधित प्रश्न में एक समान उत्तर: कुंजी संरक्षित करते समय PHP बहुआयामी सरणी से गुजरता है

मैं विशेष रूप से निश्चित नहीं हूं, लेकिन द्वितीय ने अतीत में इसका परीक्षण किया था: RecurisiveIteratorपुनरावृत्ति का उपयोग करता है, इसलिए यह इस बात पर निर्भर करता है कि आपको वास्तव में क्या चाहिए। साथ ही ढेर के आधार पर एक पुनरावर्ती पुनरावृत्ति बनाना संभव होना चाहिए:

foreach(new FlatRecursiveArrayIterator($array) as $key => $value)
{
    echo "** ($key) $value\n";
}

डेमो

मैंने इसे अभी तक नहीं बनाया है, RecursiveIteratorजिसके आधार पर स्टैक को लागू करने के लिए मुझे लगता है कि यह एक अच्छा विचार है।


बकाया array_flatten फ़ंक्शन के लिए +1। मुझे if(!empty($value)){$flat[] = $value}परिणाम सरणी में जोड़े जाने वाले खाली को रोकने के लिए अन्य विवरण के अंदर जोड़ना था । बहुत बढ़िया समारोह!
एलेक्स सरनॉस्की

19

सीधा और वन-लाइनर जवाब।

function flatten_array(array $array)
{
    return iterator_to_array(
         new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array)));
}

उपयोग:

$array = [
    'name' => 'Allen Linatoc',
    'profile' => [
        'age' => 21,
        'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
    ]
];

print_r( flatten_array($array) );

आउटपुट (PsySH में):

Array
(
    [name] => Allen Linatoc
    [age] => 21
    [0] => Call of Duty
    [1] => Titanfall
    [2] => Far Cry
)

अब यह आप पर निर्भर है कि आप चाबियों को कैसे संभालेंगे। चियर्स


EDIT (2017-03-01)

क्विटिंग निगेल एल्डर्टन की चिंता / मुद्दा:

बस स्पष्ट करने के लिए, यह कुंजी (यहां तक ​​कि संख्यात्मक) को संरक्षित करता है ताकि समान कुंजी वाले मान खो जाएं। उदाहरण के लिए $array = ['a',['b','c']]बन जाता है Array ([0] => b, [1] => c )'a'खो दिया है क्योंकि 'b'यह भी की एक प्रमुख है0

स्विश का जवाब उद्धृत करते हुए :

बस itter_to_array कॉल के ($use_keys)लिए दूसरे पैरामीटर के रूप में गलत जोड़ें


बस स्पष्ट करने के लिए, यह कुंजी (यहां तक ​​कि संख्यात्मक) को संरक्षित करता है ताकि समान कुंजी वाले मान खो जाएं। उदाहरण के लिए $array = ['a',['b','c']]बन जाता है Array ([0] => b, [1] => c )'a'खो दिया है क्योंकि है 'b'भी की एक प्रमुख है 0
निगेल एल्डर्टन

1
@NigelAlderton कॉल falseमें दूसरे पैरामीटर ( $use_keys) के रूप में जोड़ें iterator_to_array
शविश

18

पुनरावृत्ति का उपयोग करता है। उम्मीद है कि यह नहीं है कि यह कितना जटिल है, एक बार जब आप देखते हैं कि यह कैसे जटिल है तो आपकी पुनरावृत्ति का डर दूर हो जाएगा।

function flatten($array) {
    if (!is_array($array)) {
        // nothing to do if it's not an array
        return array($array);
    }

    $result = array();
    foreach ($array as $value) {
        // explode the sub-array, and add the parts
        $result = array_merge($result, flatten($value));
    }

    return $result;
}


$arr = array('foo', array('nobody', 'expects', array('another', 'level'), 'the', 'Spanish', 'Inquisition'), 'bar');
echo '<ul>';
foreach (flatten($arr) as $value) {
    echo '<li>', $value, '</li>';
}
echo '<ul>';

आउटपुट:

<ul><li>foo</li><li>nobody</li><li>expects</li><li>another</li><li>level</li><li>the</li><li>Spanish</li><li>Inquisition</li><li>bar</li><ul>

1
मैं पुनरावृत्ति से डरता नहीं हूं, मैं सिर्फ यही करने के अन्य तरीके सीखना चाहता हूं।
एलिक्स एक्सल

13
इस पुनरावृत्ति के लिए +1: आशा है कि यह जटिल नहीं है, यह देखते हुए कि आपके पुनरावृत्ति का डर एक बार आप यह देख लेंगे कि यह कितना जटिल है।
Tiberiu-Ionuț स्टेन

1
ठीक है, यह मेरे ऊपर है। यह कैसे संभव है, वह उत्तर ("मुझे पुनरावृत्ति का भय नहीं है") प्रारंभिक विवरण की तुलना में साढ़े तीन साल पुराना है (अगस्त 24 '09) ("(...) आपकी पुनरावृत्ति का भय नष्ट हो जाएगा (... ) "), 5 फरवरी 13 को बनाया गया?
ट्रेडर

18

बस मैंने सोचा था कि यह एक गुना है, इसलिए array_reduce का उपयोग किया जा सकता है:

array_reduce($my_array, 'array_merge', array());

EDIT: ध्यान दें कि यह किसी भी स्तर के समतल करने के लिए बनाया जा सकता है। हम इसे कई तरीकों से कर सकते हैं:

// Reduces one level
$concat   = function($x) { return array_reduce($x, 'array_merge', array()); };

// We can compose $concat with itself $n times, then apply it to $x
// This can overflow the stack for large $n
$compose  = function($f, $g) {
    return function($x) use ($f, $g) { return $f($g($x)); };
};
$identity = function($x) { return $x; };
$flattenA = function($n) use ($compose, $identity, $concat) {
    return  function($x) use ($compose, $identity, $concat, $n) {
        return ($n === 0)? $x
                         : call_user_func(array_reduce(array_fill(0, $n, $concat),
                                                       $compose,
                                                       $identity),
                                          $x);
    };
};

// We can iteratively apply $concat to $x, $n times
$uncurriedFlip     = function($f) {
    return  function($a, $b) use ($f) {
        return $f($b, $a);
    };
};
$iterate  = function($f) use ($uncurriedFlip) {
    return  function($n) use ($uncurriedFlip, $f) {
    return  function($x) use ($uncurriedFlip, $f, $n) {
        return ($n === 0)? $x
                         : array_reduce(array_fill(0, $n, $f),
                                        $uncurriedFlip('call_user_func'),
                                        $x);
    }; };
};
$flattenB = $iterate($concat);

// Example usage:
$apply    = function($f, $x) {
    return $f($x);
};
$curriedFlip = function($f) {
    return  function($a) use ($f) {
    return  function($b) use ($f, $a) {
        return $f($b, $a);
    }; };
};

var_dump(
    array_map(
        call_user_func($curriedFlip($apply),
                       array(array(array('A', 'B', 'C'),
                                   array('D')),
                             array(array(),
                                   array('E')))),
        array($flattenA(2), $flattenB(2))));

बेशक, हम लूप का उपयोग भी कर सकते हैं लेकिन सवाल array_map या array_values ​​की तर्ज पर एक कॉम्बिनेटर फ़ंक्शन के लिए पूछता है।


बहु-आयामी! = द्वि-आयामी।
एलिक्स एक्सल

@atamur यह PHP 5.3+ पर काम करता है। जैसा कि array_reduce के लिए चैंजोग में उल्लेख किया गया है, $ प्रारंभिक केवल 5.3 से पहले पूर्णांक हो सकता है, फिर इसे "मिश्रित" होने की अनुमति दी गई थी (यानी कुछ भी आपके फ़ंक्शन को कम करने का समर्थन करता है)
वॉरबो

1
@ ऐलेक्सएक्स आप सही कह रहे हैं कि बहु-आयामी! = द्वि-आयामी, लेकिन इसे किसी भी स्तर के समतल करने के लिए बनाया जा सकता है। सिलवटों की रचना का एक अच्छा परिणाम यह है कि यह एक निश्चित सीमा का पालन करता है; अगर मेरे पास 5 स्तरों के लिए नेस्टेड है, तो मैं foldइसे 4 स्तरों में कर सकता हूं , या fold . foldइसे 3 स्तरों को प्राप्त करने के लिए, या fold . fold . foldइसे 2 स्तरों को प्राप्त करने के लिए, आदि। यह बग्स को छिपने से भी रोकता है; जैसे। अगर मैं 5D सरणी को समतल करना चाहता हूं, लेकिन मुझे 4D सरणी दी गई है, तो त्रुटि तुरंत चालू हो जाएगी।
वारबो

मुझे यह समाधान 2-आयामी सरणियों से प्यार है। बिल को पूरी तरह से फिट करता है।
टॉम ऑगर

मैं मानता हूं कि आपकी एकल स्तर की परिभाषा सबसे अच्छा उत्तर है, यह बहुत बढ़िया है। हालाँकि मुझे लगता है कि आपने इसे गलत तरीके से नाम दिया है $concat, मुझे लगता है कि आपको इसे कॉल करना चाहिए $flattenarray_mergephp समतल के समतुल्य है। मैंने इसके लिए array_concatएक उपनाम के रूप में जुड़ने की कोशिश कीarray_merge
icc97

9

केवल दो आयामी सरणियाँ समतल करें:

$arr = [1, 2, [3, 4]];
$arr = array_reduce($arr, function ($a, $b) {
     return array_merge($a, (array) $b);
}, []);

// Result: [1, 2, 3, 4]

5

यह समाधान गैर-पुनरावर्ती है। ध्यान दें कि तत्वों का क्रम कुछ मिश्रित होगा।

function flatten($array) {
    $return = array();
    while(count($array)) {
        $value = array_shift($array);
        if(is_array($value))
            foreach($value as $sub)
                $array[] = $sub;
        else
            $return[] = $value;
    }
    return $return;
}

1
चतुर विचार, लेकिन एक बग है। "$ सरणी [] = $ मूल्य" $ मूल्य के सभी तत्वों को $ सरणी में नहीं जोड़ता है, यह केवल $ मूल्य जोड़ता है। यदि आप इस कोड को चलाते हैं, तो यह अनिश्चित काल तक लूप करेगा।
टोड ओवेन

हाँ, shiftingसरणी से मान और अंत में इसे फिर से जोड़ना बहुत मायने नहीं रखता है। मुझे लगता है कि आप array_merge()इसके बजाय चाहते थे ?
deceze

4

मेरा मानना ​​है कि किसी भी म्यूटेशन और अपरिचित वर्गों का उपयोग किए बिना यह सबसे साफ समाधान है।

<?php

function flatten($array)
{
    return array_reduce($array, function($acc, $item){
        return array_merge($acc, is_array($item) ? flatten($item) : [$item]);
    }, []);
}


// usage
$array = [1, 2, [3, 4], [5, [6, 7]], 8, 9, 10];
print_r(flatten($array));

3

निम्नलिखित सरल कार्य का प्रयास करें:

function _flatten_array($arr) {
  while ($arr) {
    list($key, $value) = each($arr); 
    is_array($value) ? $arr = $value : $out[$key] = $value;
    unset($arr[$key]);
  }
  return (array)$out;
}

तो इस से:

array (
  'und' => 
  array (
    'profiles' => 
    array (
      0 => 
      array (
        'commerce_customer_address' => 
        array (
          'und' => 
          array (
            0 => 
            array (
              'first_name' => 'First name',
              'last_name' => 'Last name',
              'thoroughfare' => 'Address 1',
              'premise' => 'Address 2',
              'locality' => 'Town/City',
              'administrative_area' => 'County',
              'postal_code' => 'Postcode',
            ),
          ),
        ),
      ),
    ),
  ),
)

आपको मिला:

array (
  'first_name' => 'First name',
  'last_name' => 'Last name',
  'thoroughfare' => 'Address 1',
  'premise' => 'Address 2',
  'locality' => 'Town/City',
  'administrative_area' => 'County',
  'postal_code' => 'Postcode',
)

हो सकता है कि आपको अपने कार्य की जांच करनी चाहिए ... ऐसा लगता है जैसे कोई काम अपेक्षित नहीं है
एमिलियानो

@ ईमिलियानो एक नया सवाल पूछने की कोशिश करें, हो सकता है कि आपका इनपुट डेटा अलग हो, इसलिए यह आपके विशेष मामले में काम नहीं करेगा।
कीनोरब

हमारे पास कुछ समस्याएँ हैं, प्रत्येक एक पदावनत किया गया कार्य है, आप उस बिंदु को बेहतर बना सकते हैं कि आप यहाँ एक नए व्यक्ति नहीं थे, आपको यह जानना चाहिए कि यदि आपका कोड php के विशिष्ट संस्करण के साथ काम करता है तो इसे तीसरा कहें यदि सभी डेटा के साथ काम न करें।
एमिलियानो

2

चाल स्रोत और गंतव्य सरणियों दोनों को संदर्भ द्वारा पारित कर रही है।

function flatten_array(&$arr, &$dst) {
    if(!isset($dst) || !is_array($dst)) {
        $dst = array();
    }
    if(!is_array($arr)) {
        $dst[] = $arr;
    } else {
        foreach($arr as &$subject) {
            flatten_array($subject, $dst);
        }
    }
}

$recursive = array('1', array('2','3',array('4',array('5','6')),'7',array(array(array('8'),'9'),'10')));
echo "Recursive: \r\n";
print_r($recursive);
$flat = null;
flatten_array($recursive, $flat);

echo "Flat: \r\n";
print_r($flat);

// If you change line 3 to $dst[] = &$arr; , you won't waste memory,
// since all you're doing is copying references, and imploding the array 
// into a string will be both memory efficient and fast:)

echo "String:\r\n";
echo implode(',',$flat);

2
/**
 * For merging values of a multidimensional array into one 
 *
 * $array = [
 *     0 => [
 *         0 => 'a1',
 *         1 => 'b1',
 *         2 => 'c1',
 *         3 => 'd1'
 *     ],
 *     1 => [
 *         0 => 'a2',
 *         1 => 'b2',
 *         2 => 'c2',
 *     ]
 * ];
 *
 * becomes : 
 *
 * $array = [
 *     0 => 'a1',
 *     1 => 'b1',
 *     2 => 'c1',
 *     3 => 'd1',
 *     4 => 'a2',
 *     5 => 'b2',
 *     6 => 'c2',
 *     
 * ]
 */
array_reduce
(
    $multiArray
    , function ($lastItem, $currentItem) {
        $lastItem = $lastItem ?: array();
        return array_merge($lastItem, array_values($currentItem));
    }
);

झपकी लेना


यह केवल द्वि-आयामी सरणियों का समर्थन करता है।
एलिक्स एक्सल

तुम सही हो। इसका उपयोग करने का कोई मतलब नहीं है। मुझे लगता है कि सबसे अच्छा समाधान "बहुत ज्यादा php" का जवाब है।
अरशम


2

यदि आप वास्तव में एक पुनरावृत्ति पसंद नहीं करते हैं ... इसके बजाय स्थानांतरण की कोशिश करें :)

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
$o = [];
for ($i=0; $i<count($a); $i++) {
    if (is_array($a[$i])) {
        array_splice($a, $i+1, 0, $a[$i]);
    } else {
        $o[] = $a[$i];
    }
}

नोट: इस सरल संस्करण में, यह सरणी कुंजियों का समर्थन नहीं करता है।


यह एक दिलचस्प तरीका है। अन्य समाधानों के विपरीत, यह मूल सरणी ($ a) को संपादित करता है। यदि आप इसे एक के साथ प्रतिस्थापित करते हैं continue, तो यह कुछ हद तक तेज है।
pcarvalho

2

कैसे एक पुनरावर्ती जनरेटर का उपयोग करने के बारे में? https://ideone.com/d0TXCg

<?php

$array = [
    'name' => 'Allen Linatoc',
    'profile' => [
        'age' => 21,
        'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
    ]
];

foreach (iterate($array) as $item) {
    var_dump($item);
};

function iterate($array)
{
    foreach ($array as $item) {
        if (is_array($item)) {
            yield from iterate($item);
        } else {
            yield $item;
        }
    }
}

1

Php 5.2 के लिए

function flatten(array $array) {
    $result = array();

    if (is_array($array)) {
        foreach ($array as $k => $v) {
            if (is_array($v)) {
                $result = array_merge($result, flatten($v));
            } else {
                $result[] = $v;
            }
        }
    }

    return $result;
}

कृपया इस कोड-केवल उत्तर के साथ कुछ स्पष्टीकरण शामिल करें।
मिकमैकुसा

1

यह संस्करण गहरे, उथले या विशिष्ट स्तर का कर सकता है:

/**
 * @param  array|object $array  array of mixed values to flatten
 * @param  int|boolean  $level  0:deep, 1:shallow, 2:2 levels, 3...
 * @return array
 */
function flatten($array, $level = 0) {
    $level = (int) $level;
    $result = array();
    foreach ($array as $i => $v) {
        if (0 <= $level && is_array($v)) {
            $v = flatten($v, $level > 1 ? $level - 1 : 0 - $level);
            $result = array_merge($result, $v);
        } elseif (is_int($i)) {
            $result[] = $v;
        } else {
            $result[$i] = $v; 
        }
    }
    return $result;
}

यह बताने से परे कि यह स्निपेट क्या कर सकता है, कृपया भविष्य के शोधकर्ताओं को बताएं कि यह कैसे काम करता है।
मिकमैकुसा

1

क्योंकि में कोड यहाँ डरावना लग रहा है। यहां एक फ़ंक्शन है जो एक बहुआयामी सरणी को html रूप में संगत सिंटैक्स में परिवर्तित करेगा, लेकिन जो पढ़ना आसान है।

/**
 * Flattens a multi demensional array into a one dimensional
 * to be compatible with hidden html fields.
 *
 * @param array $array
 *  Array in the form:
 *  array(
 *    'a' => array(
 *      'b' => '1'
 *    )
 *  )
 *
 * @return array
 *  Array in the form:
 *  array(
 *    'a[b]' => 1,
 *  )
 */
function flatten_array($array) {
  // Continue until $array is a one-dimensional array.
  $continue = TRUE;
  while ($continue) {
    $continue = FALSE;

    // Walk through top and second level of $array and move 
    // all values in the second level up one level.
    foreach ($array as $key => $value) {
      if (is_array($value)) {
        // Second level found, therefore continue.
        $continue = TRUE;

        // Move each value a level up.
        foreach ($value as $child_key => $child_value) {
          $array[$key . '[' . $child_key . ']'] = $child_value;
        }

        // Remove second level array from top level.
        unset($array[$key]);
      }
    }
  }

  return $array;
}

1

इसका उपयोग करके प्राप्त किया जा सकता है array_walk_recursive

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
array_walk_recursive($a, function($v) use (&$r){$r[]=$v;});
print_r($r);

काम करने का उदाहरण: - https://3v4l.org/FpIrG


0

एक संदर्भ का उपयोग करते हुए यह मेरा समाधान है:

function arrayFlatten($array_in, &$array_out){

    if(is_array($array_in)){
        foreach ($array_in as $element){
               arrayFlatten($element, $array_out);
        }
    }
    else{
        $array_out[] = $array_in; 
    }
}

$arr1 = array('1', '2', array(array(array('3'), '4', '5')), array(array('6')));

arrayFlatten($arr1, $arr2);

echo "<pre>";
print_r($arr2);
echo "</pre>";

कृपया कुछ स्पष्टीकरण शामिल करें कि आपका स्निपेट कैसे काम करता है और यह एक अच्छा विचार क्यों है। कोड-ओनली उत्तर स्टैकऑवरफ्लो पर कम मूल्य वाले हैं क्योंकि वे ओपी और भविष्य के शोधकर्ताओं को शिक्षित / सशक्त बनाने का एक खराब काम करते हैं। याद रखें, हम कभी भी ओपी से बात नहीं करते हैं; पुराने पन्नों का उपयोग नए पन्नों को बंद करने के लिए किया जाता है, इसलिए भविष्य के प्रश्नकर्ताओं के लिए मुद्दों को हल करने के लिए पृष्ठों को पर्याप्त जानकारीपूर्ण होना चाहिए।
मिकमैकुसा

0
<?php
//recursive solution

//test array
$nested_array = [[1,2,[3]],4,[5],[[[6,[7=>[7,8,9,10]]]]]];

/*-----------------------------------------
function call and return result to an array
------------------------------------------*/
$index_count = 1;
$flatered_array = array();
$flatered_array = flat_array($nested_array, $index_count);

/*-----------------------------------------
Print Result
-----------------------------------------*/
echo "<pre>";
print_r($flatered_array);


/*-----------------------------------------
function to flaten an array 
-----------------------------------------*/
function flat_array($nested_array, & $index_count, & $flatered_array) {

  foreach($nested_array AS $key=>$val) {
      if(is_array($val)) {
        flat_array($val, $index_count, $flatered_array);
      }
      else {
        $flatered_array[$index_count] = $val;
        ++$index_count;
      }      
  }

return $flatered_array;
}
?>

0

यहाँ एक सरल दृष्टिकोण है:

$My_Array = array(1,2,array(3,4, array(5,6,7), 8), 9);

function checkArray($value) {
    foreach ($value as $var) {
        if ( is_array($var) ) {
            checkArray($var);
        } else {
            echo $var;
        }
    }
}

checkArray($My_Array);

0

किसी को भी इस के लिए एक बहुत साफ समाधान की तलाश; यहाँ एक विकल्प है:

$test_array = array(
    array('test' => 0, 0, 0, 0),
    array(0, 0, 'merp' => array('herp' => 'derp'), 0),
    array(0, 0, 0, 0),
    array(0, 0, 0, 0)
);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($test_array));
var_dump( iterator_to_array($it, false) ) ; 

प्रिंटों

 0 0 0 0 0 0 derp 0 0 0 0 0 0 0 0 0

0

बस कुछ और समाधान पोस्ट करना)

function flatMultidimensionalArray(array &$_arr): array
{
    $result = [];
    \array_walk_recursive($_arr, static function (&$value, &$key) use (&$result) {
        $result[$key] = $value;
    });

    return $result;
}

0

यदि आप भी अपनी चाबी रखना चाहते हैं जो समाधान है।

function reduce(array $array) {
    $return = array();
    array_walk_recursive($array, function($value, $key) use (&$return) { $return[$key] = $value; });
    return $return;
}

दुर्भाग्य से यह मध्य कुंजियों के बिना केवल अंतिम नेस्टेड सरणियों का उत्पादन करता है। तो निम्न उदाहरण के लिए:

$array = array(
    'sweet' => array(
        'a' => 'apple',
        'b' => 'banana'),
    'sour' => 'lemon'); 
print_r(flatten($fruits));

आउटपुट है:

Array
(
    [a] => apple
    [b] => banana
    [sour] => lemon
)

-1

मुझे HTML इनपुट प्रारूप में PHP बहुआयामी सरणी का प्रतिनिधित्व करने की आवश्यकता थी।

$test = [
    'a' => [
        'b' => [
            'c' => ['a', 'b']
        ]
    ],
    'b' => 'c',
    'c' => [
        'd' => 'e'
    ]
];

$flatten = function ($input, $parent = []) use (&$flatten) {
    $return = [];

    foreach ($input as $k => $v) {
        if (is_array($v)) {
            $return = array_merge($return, $flatten($v, array_merge($parent, [$k])));
        } else {
            if ($parent) {
                $key = implode('][', $parent) . '][' . $k . ']';

                if (substr_count($key, ']') != substr_count($key, '[')) {
                    $key = preg_replace('/\]/', '', $key, 1);
                }
            } else {
                $key = $k;
            }           

            $return[$key] = $v;
        }
    }

    return $return;
};

die(var_dump( $flatten($test) ));

array(4) {
  ["a[b][c][0]"]=>
  string(1) "a"
  ["a[b][c][1]"]=>
  string(1) "b"
  ["b"]=>
  string(1) "c"
  ["c[d]"]=>
  string(1) "e"
}


@AlixAxel यह टिप्पणी कैसे सापेक्ष है? गलत पोस्ट ..?
गजस

नहीं, मुझे लगा कि आप जो कर रहे हैं, वह काफी हद तक वैसा ही है और इसे साझा करने का फैसला किया है, मुझे लगता है कि अंतर केवल इतना है कि मेरा प्रतिनिधित्व वैध PHP के साथ-साथ फॉर्म का भी है $var['a']['b']['c'][0] = 'a'; ...
एलिक्स एक्सल

मुझे जानबूझकर HTML आउटपुट की आवश्यकता थी। हालांकि साझा करने के लिए धन्यवाद।
गजस

1
मुझे लगता है कि यह गलत प्रश्न का सही उत्तर है। उत्तर देते समय, कृपया प्रश्न का उत्तर देने का प्रयास करें क्योंकि यह पूछा गया है - अन्यथा पृष्ठ मुख्य मुद्दे से हट सकते हैं और भविष्य के शोधकर्ताओं को भ्रमित कर सकते हैं।
मिकमैकुसा

-1

यदि आपके पास वस्तुओं का एक सरणी है और इसे एक नोड के साथ समतल करना चाहते हैं, तो बस इस फ़ंक्शन का उपयोग करें:

function objectArray_flatten($array,$childField) {
    $result = array();
    foreach ($array as $node)
    {
        $result[] = $node;
        if(isset($node->$childField))
        {
            $result = array_merge(
                $result, 
                objectArray_flatten($node->$childField,$childField)
            );
            unset($node->$childField);
        }

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