Bagaimana cara Meratakan Array Multidimensi?


259

Apakah mungkin, dalam PHP, untuk meratakan array dimensi (bi / multi) tanpa menggunakan rekursi atau referensi?

Saya hanya tertarik pada nilai-nilai sehingga kunci dapat diabaikan, saya berpikir dalam garis array_map()dan array_values().


17
Mengapa menghindari rekursi?
JorenB


4
Anda tidak dapat melakukan apa pun dengan semua elemen array yang sewenang-wenang mendalam tanpa rekursi (Anda dapat menyamarkannya sebagai iterasi, tetapi kentang, potahto.) Jika Anda hanya ingin menghindari menulis kode penanganan rekursi sendiri, gunakan dk2.php.net/ manual / en / function.array-walk-recursive.php dengan panggilan balik yang menambahkan elemen ke array yang tersedia (gunakan global, parameter data pengguna, letakkan semuanya di dalam kelas dan lihat $ this, dll.)
Michael Madsen

@JorenB: Saya ingin melihat implementasi dapat diarsipkan.
Alix Axel

Silahkan lihat pada meratakan fungsi dari Nspl . Anda juga dapat menentukan kedalamannya.
Ihor Burlachenko

Jawaban:


276

Anda dapat menggunakan Perpustakaan PHP Standar (SPL) untuk "menyembunyikan" rekursi.

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

cetakan

1 2 3 4 5 6 7 8 9 

351
Apakah saya satu-satunya yang berpikir 'RecursiveIteratorIterator' adalah nama yang konyol?
nilamo

45
Ini lebih "logis" daripada "catchy". Tidak semuanya dapat memiliki nama yang fantastis seperti JOGL, Knol atau Azure :-)
VolkerK

7
Ini tidak akan berfungsi untuk array kosong sebagai anak-anak. Mereka akan dikembalikan sebagai orangtua.
hakre

45
iterator_to_array($it, false)menghindari perlunya foreach.
Alix Axel

3
Berdasarkan apa yang disajikan orang lain, saya bisa membuat pembantu kecil ini: function flatten($arr){ $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)); return iterator_to_array($it, true); }Semoga ini bisa membantu orang lain.
Mike S.

296

Pada PHP 5.3 solusi terpendek tampaknya adalah array_walk_recursive()dengan sintaks penutupan baru:

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

33
jika Anda ingin kunci, ratakan fungsi (array $ array) {$ return = array (); array_walk_recursive ($ array, function ($ a, $ b) use (& $ return) {$ return [$ b] = $ a;}); return $ return; }
Brendon-Van-Heyzen

dapatkah Anda menulis ulang ini untuk digunakan dengan php 5.2?
Alex

2
@Alex sayangnya Anda memerlukan usesintaks untuk membuatnya bekerja array_walk_recursivekarena tidak akan menerima $userdataparameter opsional dengan referensi
Tim Seguine

1
Sepertinya berfungsi dengan baik untuk Array tersebut -> ideone.com/DsmApP Tapi tidak untuk yang seperti itu -> ideone.com/5Kltva Atau apakah saya?
Sebastian Piskorski

2
@Sebastian Piskorski itu karena nilai Anda diperlakukan seperti kunci, jadi segera setelah Anda memperkenalkan pasangan kunci Anda => pasangan nilai dalam sebuah array, nilai array Anda di posisi indeks pertama diperlakukan seperti kunci tanpa nilai, dan karena kunci memiliki menjadi unik, di mana dua tombol cocok, nilai-nilai Anda ditambahkan ke kunci yang sama. Solusi sederhana adalah dengan mengurutkan array terlebih dahulu. Ini adalah perilaku yang melekat dalam PHP.
Martyn Shutt

92

Solusi untuk array 2 dimensi

Silakan coba ini:

$array  = your array

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

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

EDIT: 21-Aug-13

Inilah solusi yang berfungsi untuk array multi dimensi:

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


Terima kasih, yang pertama bekerja pada array yang saya dapatkan dari PDO di mana solusi lain tidak.
JAL

7
Ini adalah strategi yang buruk. call_user_func_array('array_merge', [])(perhatikan array kosong) mengembalikan nol dan memicu kesalahan peringatan php. Ini adalah solusi yang apik jika Anda tahu fakta bahwa array Anda tidak akan kosong, tapi itu bukan asumsi umum yang bisa dibuat banyak orang.
kambing

OP secara khusus meminta solusi non-rekursif.
Élektra

Wow, keren 2d flattern! Tetapi untuk mencegah pemberitahuan gunakan saja$result = $array ?call_user_func_array('array_merge', $array) : [];
Alexander Goncharov

keren bruh, tapi bukankah Anda secara kebetulan memiliki fungsi counter-deflatten?
FantomX1

64

Dalam PHP 5.6 dan di atasnya Anda dapat meratakan array dua dimensi dengan array_mergesetelah membongkar array luar dengan ...operator. Kode ini sederhana dan jelas.

array_merge(...$a);

Ini bekerja dengan kumpulan array asosiatif juga.

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

Tapi itu tidak berfungsi ketika array luar memiliki kunci non numerik. Dalam hal ini, Anda harus menelepon array_valuesdulu.

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

Pembaruan: Berdasarkan komentar oleh @MohamedGharib

Ini akan menimbulkan kesalahan jika array luar kosong, karena array_mergeakan dipanggil dengan argumen nol. Ini bisa dihindari dengan menambahkan array kosong sebagai argumen pertama.

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

1
Ini HANYA berfungsi ketika setiap elemen array adalah array. Jika array terdiri dari tipe campuran, seperti skalar, kesalahan akan terjadi.
Otheus

@Otheus Itu karena solusi di atas tidak menggunakan rekursi. Seperti yang Anda katakan, itu membutuhkan array array. Tetapi di sisi positifnya, ini harus jauh lebih cepat daripada metode lain, karena tidak memiliki overhead tambahan dari panggilan fungsi.
Joyce Babu

2
Akan melempar kesalahan jika array luar kosong, bisa dihindari jika dikombinasikan dengan array kosongarray_merge([], ...$a);
Mohamed Gharib

@MohamedGharib Tangkapan bagus.
Joyce Babu

Jika menggunakan array asosiatif Anda dapat memeriksa solusi ini stackoverflow.com/questions/40663687/…
alex

24

Untuk meratakan tanpa rekursi (seperti yang Anda minta), Anda dapat menggunakan tumpukan . Secara alami Anda dapat menempatkan ini ke dalam fungsi itu sendiri seperti array_flatten. Berikut ini adalah versi yang berfungsi tanpa kunci :.

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

Elemen diproses dalam urutannya. Karena subelemen akan dipindahkan di atas tumpukan, mereka akan diproses berikutnya.

Dimungkinkan juga untuk memasukkan kunci, tetapi Anda memerlukan strategi berbeda untuk menangani tumpukan. Itu diperlukan karena Anda perlu menangani kemungkinan kunci duplikat di sub-array. Jawaban serupa dalam pertanyaan terkait: PHP Berjalan melalui array multidimensi sambil mempertahankan kunci

Saya tidak terlalu yakin, tetapi saya telah menguji ini di masa lalu: RecurisiveIteratorMenggunakan rekursi, jadi itu tergantung pada apa yang Anda butuhkan. Seharusnya dimungkinkan untuk membuat iterator rekursif berdasarkan tumpukan juga:

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

Demo

Saya tidak sampai sejauh ini, untuk mengimplementasikan stack berdasarkan RecursiveIteratoryang menurut saya adalah ide yang bagus.


+1 untuk fungsi array_flatten yang luar biasa. Saya harus menambahkan if(!empty($value)){$flat[] = $value}di dalam pernyataan lain untuk mencegah kosong yang ditambahkan ke array hasil. Fungsi luar biasa!
Alex Sarnowski

19

Langsung dan Satu-liner jawaban.

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

Pemakaian:

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

print_r( flatten_array($array) );

Output (dalam PsySH):

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

Sekarang terserah Anda sekarang bagaimana Anda akan menangani kunci. Bersulang


EDIT (2017-03-01)

Mengutip kekhawatiran / masalah Nigel Alderton :

Hanya untuk memperjelas, ini mempertahankan kunci (bahkan angka) sehingga nilai yang memiliki kunci yang sama hilang. Misalnya $array = ['a',['b','c']]menjadi Array ([0] => b, [1] => c ). The 'a'hilang karena 'b'juga memiliki kunci0

Mengutip jawaban Svish :

Tambahkan saja false sebagai parameter kedua ($use_keys)ke panggilan iterator_to_array


Hanya untuk memperjelas, ini mempertahankan kunci (bahkan angka) sehingga nilai yang memiliki kunci yang sama hilang. Misalnya $array = ['a',['b','c']]menjadi Array ([0] => b, [1] => c ). The 'a'hilang karena 'b'juga memiliki kunci 0.
Nigel Alderton

1
@NigelAlderton Cukup tambahkan falsesebagai parameter kedua ( $use_keys) ke iterator_to_arraypanggilan.
Svish

18

Gunakan rekursi. Mudah-mudahan setelah melihat betapa tidak rumitnya hal itu, ketakutan Anda akan rekursi akan hilang begitu Anda melihat betapa tidak rumitnya itu.

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

Keluaran:

<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
Saya tidak takut rekursi, saya hanya ingin belajar cara lain untuk melakukan hal yang sama.
Alix Axel

13
+1 untuk rekursi ini: Mudah-mudahan setelah melihat betapa tidak rumitnya hal ini, ketakutan Anda akan rekursi akan hilang begitu Anda melihat betapa tidak rumitnya itu.
Tiberiu-Ionuț Stan

1
Oke, ini sudah berakhir. Bagaimana mungkin, jawaban itu ("Saya tidak takut rekursi") adalah tiga setengah tahun lebih tua (24 Agustus 2009) daripada pernyataan awal ("... ... ketakutan rekursi Anda akan hilang (... ) "), dibuat pada 5 Februari '13?
trejder

18

Hanya berpikir saya akan menunjukkan bahwa ini adalah lipatan, jadi array_reduce dapat digunakan:

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

EDIT: Perhatikan bahwa ini dapat disusun untuk meratakan sejumlah level. Kita dapat melakukan ini dalam beberapa cara:

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

Tentu saja, kita juga bisa menggunakan loop tetapi pertanyaannya meminta fungsi kombinator di sepanjang baris array_map atau array_values.


Multi-dimensional! = Bi-dimensional.
Alix Axel

@atamur Ini berfungsi pada PHP 5.3+. Seperti tercantum dalam changelog untuk array_reduce, $ initial hanya bisa berupa bilangan bulat sebelum 5.3, lalu diizinkan untuk "dicampur" (mis. Apa pun yang didukung fungsi reduksi Anda)
Warbo

1
@AlixAxel Anda benar multi-dimensional! = Bi-dimensional, tetapi ini dapat dikomposisikan untuk meratakan sejumlah level. Salah satu konsekuensi yang baik dari penyusunan lipatan adalah bahwa ia mematuhi batas tetap; jika saya memiliki array yang bersarang hingga 5 level, saya dapat foldmembuatnya menjadi 4 level, atau fold . folduntuk mendapatkan 3 level, atau fold . fold . folduntuk mendapatkan 2 level, dll. Ini juga mencegah bug disembunyikan; misalnya. jika saya ingin meratakan array 5D tapi saya diberi array 4D, kesalahan akan langsung terpicu.
Warbo

Saya suka solusi ini, untuk array 2 dimensi. Pas dengan tagihan.
Tom Auger

Saya setuju bahwa definisi level tunggal Anda adalah jawaban terbaik, juga sangat bagus. Namun saya pikir Anda salah menyebutkan namanya $concat, saya pikir Anda harus menyebutnya saja $flatten. array_mergeadalah setara dengan php dari concat. Saya mencoba untuk array_concatditambahkan sebagai alias untuk array_merge.
icc97

9

Ratakan hanya array dua dimensi:

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

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

5

Solusi ini non-rekursif. Perhatikan bahwa urutan elemen akan agak tercampur.

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
Ide cerdik, tapi ada bug. "$ array [] = $ value" tidak menambahkan semua elemen $ value ke $ array, itu hanya menambah $ value itu sendiri. Jika Anda menjalankan kode ini, itu akan berulang tanpa batas.
Todd Owen

Ya, shiftingnilai dari array dan menambahkannya lagi sampai akhir tidak masuk akal. Saya kira Anda ingin array_merge()bukan?
deceze

4

Saya percaya ini adalah solusi terbersih tanpa menggunakan mutasi atau kelas yang tidak dikenal.

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

Coba fungsi sederhana berikut ini:

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

Jadi dari ini:

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

Anda mendapatkan:

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

mungkin Anda harus memeriksa fungsi Anda ... sepertinya tidak bekerja seperti yang diharapkan
Emiliano

@Emiliano Cobalah mengajukan pertanyaan baru, mungkin data masukan Anda berbeda, sehingga tidak akan berfungsi dalam kasus khusus Anda.
kenorb

kami memiliki beberapa masalah masing-masing adalah fungsi yang sudah usang, Anda dapat meningkatkan bahwa Anda bukan orang baru di sini, Anda harus tahu itu kedua jika kode Anda bekerja dengan versi tertentu dari php mengatakannya ketiga jika tidak bekerja dengan semua data katakan itu
Emiliano

2

Triknya adalah melewati array sumber dan tujuan dengan referensi.

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

Cuplikan inti


Ini tampaknya hanya mendukung array dua dimensi.
Alix Axel

Kamu benar. Tidak ada gunanya menggunakannya. Saya pikir solusi terbaik adalah jawaban "terlalu banyak php".
Arsham


2

Jika Anda benar-benar tidak menyukai rekursi ... coba ganti saja :)

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

Catatan: Dalam versi sederhana ini, ini tidak mendukung kunci array.


ini merupakan pendekatan yang menarik. berbeda dengan solusi lain, itu mengedit array asli ($ a). Jika Anda menggantinya dengan continue, itu agak lebih cepat.
pcarvalho

2

Bagaimana dengan menggunakan generator rekursif? 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

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

Harap sertakan beberapa penjelasan dengan jawaban hanya kode ini.
mickmackusa

1

Versi ini dapat melakukan level yang dalam, dangkal, atau jumlah tertentu:

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

Di luar menjelaskan apa yang dapat dilakukan cuplikan ini , tolong jelaskan kepada peneliti di masa depan bagaimana cara kerjanya.
mickmackusa

1

Karena kode di sini terlihat menyeramkan. Berikut adalah fungsi yang juga akan mengubah array multidimensi menjadi sintaks yang kompatibel dengan bentuk html, tetapi lebih mudah dibaca.

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

Ini bisa dicapai dengan menggunakan 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);

Contoh kerja: - https://3v4l.org/FpIrG


0

Ini solusi saya, menggunakan referensi:

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

Harap sertakan beberapa penjelasan tentang cara kerja cuplikan Anda dan mengapa itu ide yang bagus. Jawaban khusus kode hanya bernilai rendah di StackOverflow karena mereka melakukan pekerjaan yang buruk dalam mendidik / memberdayakan OP dan peneliti masa depan. Ingat, kita tidak pernah HANYA berbicara kepada OP; halaman lama digunakan untuk menutup halaman baru, jadi halaman harus cukup informatif untuk menyelesaikan masalah bagi penanya di masa depan.
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

Inilah pendekatan sederhana:

$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

Siapa pun yang mencari solusi yang sangat bersih untuk ini; inilah pilihannya:

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

Cetakan

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

0

Hanya memposting solusi lain)

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

    return $result;
}

0

Jika Anda ingin menyimpan juga kunci Anda, itu adalah solusi.

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

Sayangnya ini hanya menghasilkan array bersarang akhir, tanpa tombol tengah. Jadi untuk contoh berikut:

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

Output adalah:

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

-1

Saya perlu mewakili array multidimensi PHP dalam format input HTML.

$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 Bagaimana komentar ini relatif? Pos yang salah ..?
Gajus

Tidak. Saya pikir itu sangat mirip dengan apa yang Anda lakukan dan memutuskan untuk membagikannya, saya pikir satu-satunya perbedaan adalah bahwa representasi saya adalah PHP yang valid juga - dalam bentuk $var['a']['b']['c'][0] = 'a'; ....
Alix Axel

Saya sengaja membutuhkan hasil HTML. Padahal terima kasih sudah berbagi.
Gajus

1
Saya merasa ini adalah jawaban yang benar untuk pertanyaan yang salah. Saat menjawab, harap coba menjawab pertanyaan seperti yang ditanyakan - jika tidak, halaman dapat berangkat dari masalah inti dan membuat peneliti masa depan bingung.
mickmackusa

-1

Jika Anda memiliki array objek dan ingin meratakannya dengan sebuah simpul, cukup gunakan fungsi ini:

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;
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.