Çok Boyutlu Bir Dizi Nasıl Düzleştirilir?


259

PHP'de özyineleme veya referans kullanmadan bir (bi / multi) boyutlu diziyi düzleştirmek mümkün mü?

Sadece tuşları göz ardı edilebilir, böylece ben hatlarında düşünüyorum değerlere ilgilenen kulüpler array_map()ve array_values().


17
Neden özyinelemeden kaçının?
JorenB


4
Rasgele derin dizilerin tüm unsurları ile özyineleme olmadan hiçbir şey yapamazsınız (yineleme olarak gizleyebilirsiniz, ancak patates, potahto.) Özyineleme işleme kodunu kendiniz yazmaktan kaçınmak istiyorsanız, dk2.php.net/ manual / en / function.array-walk-recursive.php , öğeyi kullanılabilir bir diziye ekleyen bir geri aramayla (global, userdata parametresini kullanın, hepsini bir sınıfa koyun ve $ this, vb.
konusuna

@JorenB: Bir uygulamanın arşivlenebileceğini görmek istiyorum.
Alix Axel

Nspl'den yassılaştırma fonksiyonuna bir göz atın . Bununla birlikte bir derinlik de belirleyebilirsiniz.
Ihor Burlachenko

Yanıtlar:


276

Sen kullanabilirsiniz Standart PHP Kütüphanesi (SPL) "gizlemek" özyinelemeye.

$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, " ";
}

baskılar

1 2 3 4 5 6 7 8 9 

351
'RecursiveIteratorIterator' aptalca bir isim olduğunu düşünen tek kişi ben miyim?
nilamo

45
"Akılda kalıcı" olmaktan çok "mantıklı". Her şeyin JOGL, Knol veya Azure gibi fantastik bir adı olamaz :-)
VolkerK

7
Bu, boş diziler için çocuk olarak çalışmaz. Ebeveyn olarak iade edilecekler.
hakre

45
iterator_to_array($it, false)foreach ihtiyacını ortadan kaldırır.
Alix Axel

3
Başkalarının sunduklarına dayanarak, bu küçük yardımcıyı yapmayı başardım: function flatten($arr){ $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)); return iterator_to_array($it, true); }Umarım bu başkalarına yardımcı olur.
Mike

296

İtibariyle PHP 5.3 en kısa çözüm gibi görünüyor array_walk_recursive()yeni kapanışları söz dizimi ile:

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

33
tuşları istiyorsanız, flatten (dizi $ dizi) işlevini {$ return = array (); array_walk_recursive ($ dizi, işlev ($ a, $ b) kullanımı (& $ return) {$ return [$ b] = $ a;}); dönüş $ dönüş; }
Brendon-Van-Heyzen

php 5.2 ile kullanmak için yeniden yazabilir misiniz?
Alex

2
@Alex ne yazık ki usebu çalışmayı yapmak için sözdizimine ihtiyacınız var, array_walk_recursiveçünkü isteğe bağlı $userdataparametreyi referans olarak kabul
etmiyor

1
Böyle diziler için iyi çalışıyor gibi görünüyor -> ideone.com/DsmApP Ama böyle olanlar için değil -> ideone.com/5Kltva Yoksa ben miyim?
Sebastian Piskorski

2
@Sebastian Piskorski, değerlerinize anahtarlar gibi davranıldığı için, bir dizide kendi anahtar => değer çiftinizi tanıtır getirmez, ilk dizin konumundaki dizi değerleriniz değersiz anahtarlar olarak kabul edilir ve anahtarlar iki anahtarın eşleştiği yerde benzersiz olmak için değerleriniz aynı anahtara eklenir. Basit bir çözüm diziyi önce sıralamak olacaktır. Bu PHP'nin doğasında var olan bir davranıştır.
Martyn Shutt

92

2 boyutlu dizi için çözüm

Lütfen şunu deneyin:

$array  = your array

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

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

DÜZENLEME: 21-Ağu-13

İşte çok boyutlu dizi için çalışan çözüm:

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/tr/function.call-user-func-array.php


Teşekkürler, birincisi diğer çözümlerin yapmadığı PDO'dan aldığım bir dizi üzerinde çalıştı.
JAL

7
Bu zayıf bir stratejidir. call_user_func_array('array_merge', [])(boş diziye dikkat edin) null değerini döndürür ve bir php uyarı hatasını tetikler. Dizinizin boş kalmayacağı gerçeğini biliyorsanız, kaygan bir çözümdür, ancak bu birçok kişinin yapabileceği ortak bir varsayım değildir.
keçi

OP özellikle özyinelemeli olmayan çözümler istedi.
Élektra

Vay canına, havalı 2d düzleştirici! Ancak bildirimi önlemek için sadece kullanın$result = $array ?call_user_func_array('array_merge', $array) : [];
Alexander Goncharov

cool bruh, ama şans eseri karşı bir dizi dizi deflatten yok mu?
FantomX1

65

PHP 5.6 ve üzeri array_mergesürümlerde, dış diziyi ...operatörle birlikte açtıktan sonra iki boyutlu dizileri düzleştirebilirsiniz . Kod basit ve anlaşılır.

array_merge(...$a);

Bu ilişkisel dizilerin toplanmasıyla da çalışır.

$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
)

Ancak, dış dizide sayısal olmayan anahtarlar olduğunda çalışmaz. Bu durumda, array_valuesönce aramanız gerekir .

$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
)

Güncelleme: @MohamedGharib tarafından yapılan yoruma göre

Dış dizi boşsa bu hata verir, çünkü array_mergesıfır argümanıyla çağrılır. İlk argüman olarak boş bir dizi eklenerek önlenebilir.

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

1
Bu SADECE dizinin her elemanı bir dizi olduğunda çalışır. Dizi, skaler gibi karışık tipler içeriyorsa, bir hata oluşur.
Otheus

@Otheus Yukarıdaki çözüm özyineleme kullanmıyor olmasıdır. Söylediğiniz gibi, bir dizi dizi gerektirir. Ancak artı tarafta, işlev çağrılarının ek yükü olmadığından, bu diğer yöntemlerden çok daha hızlı olmalıdır.
Joyce Babu

2
Dış dizi boşsa bir hata atar, boş bir dizi ile birleştirilirse önlenebilirarray_merge([], ...$a);
Mohamed Gharib

@MohamedGharib Güzel yakala.
Joyce Babu

İlişkilendirilebilir diziler kullanıyorsanız, bu çözümü kontrol edebilirsiniz stackoverflow.com/questions/40663687/…
alex

24

Özyinelemesiz (istediğiniz gibi) düzleştirmek için bir yığın kullanabilirsiniz . Doğal olarak bunu kendi işlevine sokabilirsiniz array_flatten. Aşağıda anahtarsız çalışan bir sürüm bulunmaktadır:

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;
}

Öğeler sıralarına göre işlenir. Alt öğeler yığının üstüne taşınacağından, bir sonraki işleme alınacaktır.

Anahtarları da hesaba katmak mümkündür, ancak yığını işlemek için farklı bir stratejiye ihtiyacınız olacaktır. Alt dizilerdeki olası yinelenen anahtarlarla uğraşmanız gerektiğinden bu gereklidir. İlgili bir soruya benzer bir cevap: PHP Anahtarları korurken çok boyutlu dizi boyunca yürüyün

Özellikle emin değilim, ama II bunu geçmişte test etmişti: RecurisiveIteratorÖzyineleme kullanıyor, bu yüzden gerçekten neye ihtiyacınız olduğuna bağlı. Yığınlara dayalı bir özyinelemeli yineleyici oluşturmak mümkün olmalıdır:

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

gösteri

Şimdiye kadar, RecursiveIteratorgüzel bir fikir olduğunu düşündüğüm yığını uygulamaya koymadım.


Olağanüstü array_flatten işlevi için +1. if(!empty($value)){$flat[] = $value}Sonuç dizisine boş eklenmesini önlemek için else deyimi içinde eklemek zorunda kaldı . Müthiş fonksiyon!
Alex Sarnowski

19

Basit ve Tek astarlı cevap.

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

Kullanımı:

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

print_r( flatten_array($array) );

Çıktı (PsySH cinsinden):

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

Şimdi tuşları nasıl kullanacağınız size kalmış. Şerefe


DÜZENLE (2017-03-01)

Nigel Alderton'un endişesi / sorunundan alıntı :

Açıklığa kavuşturmak için, bu anahtarları (sayısal olanlar bile) korur, böylece aynı anahtara sahip değerler kaybolur. Örneğin $array = ['a',['b','c']]olur Array ([0] => b, [1] => c ). 'a'Çünkü kaybolur 'b'da bir anahtara sahip0

Svish'in cevabından alıntı :

Sadece ikinci parametre olarak false eklemek ($use_keys)için iterator_to_array çağrısı


Açıklığa kavuşturmak için, bu anahtarları (sayısal olanlar bile) korur, böylece aynı anahtara sahip değerler kaybolur. Örneğin $array = ['a',['b','c']]olur Array ([0] => b, [1] => c ). 'a'Çünkü kaybolur 'b'da bir anahtar vardır 0.
Nigel Alderton

1
@NigelAlderton Aramaya falseikinci parametre ( $use_keys) olarak eklemeniz yeterlidir iterator_to_array.
Svish

18

Özyineleme kullanır. Umarım ne kadar karmaşık olmadığını gördükten sonra, ne kadar karmaşık olmadığını gördüğünüzde, tekrarlama korkunuz dağılacaktır.

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>';

Çıktı:

<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
Özyinelemeden korkmuyorum, sadece aynı şeyi yapmanın başka yollarını öğrenmek istiyorum.
Alix Axel

13
Bu özyineleme için +1: Umarım ne kadar karmaşık olmadığını görünce, ne kadar karmaşık olmadığını gördüğünüzde tekrarlama korkunuz dağılacaktır.
Tiberiu-Ionuț Stan

1
Tamam, bu benim üzerimde. Nasıl mümkün, bu cevap ("özyineleme korkmuyorum") ilk açıklama ("(...) özyineleme korkunuz dağılacak (... (...) üç buçuk yaşında (24 Ağustos) ) "), 5 '13 Şubat?
trejder

18

Sadece bu bir kat olduğunu işaret düşündüm, böylece array_reduce kullanılabilir:

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

EDIT: Bunun herhangi bir sayıda seviyeyi düzleştirmek için oluşturulabileceğini unutmayın. Bunu birkaç şekilde yapabiliriz:

// 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))));

Tabii ki, döngüler de kullanabiliriz, ancak soru dizi_map veya dizi_değerleri çizgileri boyunca bir birleştirici işlevi ister.


Çok boyutlu! = İki boyutlu.
Alix Axel

@atamur PHP 5.3 ve sonraki sürümlerinde çalışır. Array_reduce için değişiklik günlüğünde belirtildiği gibi, $ initial yalnızca 5.3'ten önce bir tamsayı olabilir, daha sonra "karışık" olmasına izin verilir (yani, azaltma işlevinizin desteklediği herhangi bir şey)
Warbo

1
@AlixAxel Çok boyutlu! = İki boyutlu haklısınız, ancak bu istediğiniz sayıda seviyeyi düzleştirmek için oluşturulabilir. Kıvrım oluşturmanın güzel bir sonucu, sabit bir sınıra uymasıdır; 5 seviyeye yuvalanmış bir dizi varsa, ben fold4 seviyeye, ya fold . foldda 3 seviyeleri almak için, ya fold . fold . foldda 2 seviyeleri almak için, vb. Bu da hataların gizlenmesi önler; Örneğin. bir 5D dizisini düzleştirmek istiyorum ama bir 4D dizisi verildi, hata hemen tetikleyecektir.
Warbo

Bu çözümü 2 boyutlu diziler için seviyorum. Faturaya mükemmel uyum sağlar.
Tom Auger

Tek seviye tanımınızın en iyi cevap olduğunu kabul ediyorum, aynı zamanda harika bir şekilde temiz. Ancak yanlış adlandırdığınızı $concatdüşünüyorum, sadece çağırmanız gerektiğini düşünüyorum $flatten. array_mergeconcat'ın php eşdeğeri. Denedim almak array_concatiçin bir takma ad olarak eklendi array_merge.
icc97

9

Yalnızca iki boyutlu dizileri düzleştirir:

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

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

5

Bu çözüm özyinelemeli değildir. Elemanların sırasının biraz karışık olacağını unutmayın.

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
Zekice bir fikir, ama bir hata var. "$ array [] = $ value", $ dizisinin tüm öğelerini $ dizisine eklemez, yalnızca $ değerinin kendisini ekler. Bu kodu çalıştırırsanız, süresiz olarak döngü yapacaktır.
Todd Owen

Evet, shiftingdizinin dışındaki değer ve sonuna sonuna eklemek pek mantıklı değil. Sanırım array_merge()onun yerine istedin mi?
deceze

4

Bunun herhangi bir mutasyon veya yabancı sınıf kullanmadan en temiz çözüm olduğuna inanıyorum.

<?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

Aşağıdaki basit işlevi deneyin:

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;
}

Yani bundan:

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',
            ),
          ),
        ),
      ),
    ),
  ),
)

olsun:

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

belki fonksiyonunuzu kontrol etmelisiniz ... beklendiği gibi bir iş gibi görünmüyor
Emiliano

@Emiliano Yeni bir soru sormayı deneyin, belki giriş verileriniz farklıdır, bu nedenle sizin durumunuzda çalışmaz.
kenorb

Her biri kullanımdan kaldırılmış bir işlev olan birkaç sorun var, burada yeni bir adam olmadığınızı geliştirebilirsiniz, kodunuzun belirli bir php sürümü ile çalışması durumunda ikinci bilmelisiniz, tüm verilerle çalışmazsa üçüncü olarak söyleyin
Emiliano

2

Hile, hem kaynak hem de hedef dizileri referans olarak geçiyor.

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));
    }
);

Pasaj pasajı


Bu sadece iki boyutlu dizileri destekliyor gibi görünüyor.
Alix Axel

Haklısın. Kullanmanın bir anlamı yok. Bence en iyi çözüm "çok fazla php" nin cevabı.
Arsham


2

Gerçekten bir özyinelemeyi sevmiyorsanız ... bunun yerine kaydırmayı deneyin :)

$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];
    }
}

Not: Bu basit sürümde, dizi anahtarları desteklenmez.


bu ilginç bir yaklaşım. diğer çözümlerin aksine, orijinal diziyi ($ a) düzenler. Bir ile değiştirirseniz continue, biraz daha hızlıdır.
pcarvalho

2

Özyinelemeli bir jeneratör kullanmaya ne dersiniz? 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 için

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;
}

Lütfen yalnızca kodla ilgili bu yanıta bir açıklama ekleyin.
mickmackusa

1

Bu sürüm derin, sığ veya belirli sayıda seviye yapabilir:

/**
 * @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;
}

Bu pasajın neler yapabileceğini açıklamanın ötesinde , lütfen gelecekteki araştırmacılara nasıl çalıştığını açıklayın.
mickmackusa

1

Kod Çünkü burada korkunç görünüyor. Ayrıca çok boyutlu bir diziyi html formuyla uyumlu sözdizimine dönüştürecek, ancak okunması daha kolay olan bir işlev.

/**
 * 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

Bunu kullanarak elde edilebilir 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);

Çalışma örneği: - https://3v4l.org/FpIrG


0

Bu benim referans, bir referans kullanarak:

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>";

Lütfen snippet'inizin nasıl çalıştığına ve neden iyi bir fikir olduğuna ilişkin bazı açıklamalar ekleyin. Yalnızca kod yanıtları, OP ve gelecekteki araştırmacıları eğitmek / güçlendirmek için zayıf bir iş yaptıkları için StackOverflow'da düşük değerlidir. Unutmayın, asla SADECE OP ile konuşmayız; eski sayfalar yeni sayfaları kapatmak için kullanılır.
mickmackusa

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

İşte basit bir yaklaşım:

$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

Buna gerçekten temiz bir çözüm arayan herkes; İşte bir seçenek:

$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) ) ; 

Baskılar

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

0

Sadece başka bir çözüm yayınlamak)

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

    return $result;
}

0

Anahtarlarınızı da tutmak istiyorsanız çözüm budur.

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

Ne yazık ki, orta anahtarlar olmadan yalnızca son iç içe diziler çıkarır. Aşağıdaki örnek için:

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

Çıktı:

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

-1

PHP çok boyutlu diziyi HTML giriş biçiminde temsil etmem gerekiyordu.

$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 Bu yorum nasıl göreceli? Yanlış gönderi ..?
Gajus

Hayır. Yaptığınız şeye oldukça benzer olduğunu düşündüm ve paylaşmaya karar verdim, tek fark, temsilimin geçerli PHP'nin de formun geçerli olmasıdır $var['a']['b']['c'][0] = 'a'; ....
Alix Axel

Kasten HTML çıktısına ihtiyacım vardı. Yine de paylaştığın için teşekkürler.
Gajus

1
Bunun yanlış soruya doğru cevap olduğunu hissediyorum. Yanıtlarken, lütfen soruyu sorulduğu gibi yanıtlamaya çalışın - aksi takdirde sayfalar temel sorundan ayrılabilir ve gelecekteki araştırmacıları karışık bırakabilir.
mickmackusa

-1

Bir dizi nesneniz varsa ve bunu bir düğümle düzleştirmek istiyorsanız, şu işlevi kullanın:

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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.