it-swarm.com.ru

Как "сплющить" многомерный массив в простой в PHP?

Вероятно, это вопрос новичка, но я уже давно изучаю документацию и не могу найти никакого решения. Я думал, что смогу использовать implode для каждого измерения, а затем соединить эти строки вместе с str_split, чтобы создать новый простой массив. Однако я никогда не знаю, если шаблон соединения также не указан в значениях, и поэтому после выполнения str_split мои исходные значения могут сломаться.

Есть ли что-то вроде combine($array1, $array2) для массивов внутри многомерного массива?

68
Adriana

Используйте array_walk_recursive

<?php

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

$objTmp = (object) array('aFlat' => array());

array_walk_recursive($aNonFlat, create_function('&$v, $k, &$t', '$t->aFlat[] = $v;'), $objTmp);

var_dump($objTmp->aFlat);

/*
array(11) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
  [4]=>
  int(5)
  [5]=>
  int(6)
  [6]=>
  int(7)
  [7]=>
  int(8)
  [8]=>
  int(9)
  [9]=>
  int(10)
  [10]=>
  int(11)
}
*/

?>

Протестировано с PHP 5.5.9-1ubuntu4.24 (cli) (построено: 16 марта 2018 12:32:06)

41
Luc M
$array  = your array

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

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

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

Вот еще одно решение (работает с многомерным массивом):

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);
115
Prasanth Bendra

Это одна строка, СУПЕР прост в использовании:

$result = array();
array_walk_recursive($original_array,function($v) use (&$result){ $result[] = $v; });

Это очень легко понять, внутри анонимной функции/замыкания. $v - это значение вашего $original_array.

44
Arnold Roa
// $array = your multidimensional array

$flat_array = array();

foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $k=>$v){

$flat_array[$k] = $v;

}

Также задокументировано: http://www.phpro.org/examples/Flatten-Array.html

19
upallnite
function flatten_array($array, $preserve_keys = 0, &$out = array()) {
    # Flatten a multidimensional array to one dimension, optionally preserving keys.
    #
    # $array - the array to flatten
    # $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys
    # $out - internal use argument for recursion
    foreach($array as $key => $child)
        if(is_array($child))
            $out = flatten_array($child, $preserve_keys, $out);
        elseif($preserve_keys + is_string($key) > 1)
            $out[$key] = $child;
        else
            $out[] = $child;
    return $out;
}
5
chaos

Другой метод из PHP комментарии пользователей (упрощенно) и здесь :

function array_flatten_recursive($array) { 
   if (!$array) return false;
   $flat = array();
   $RII = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
   foreach ($RII as $value) $flat[] = $value;
   return $flat;
}

Большим преимуществом этого метода является то, что он отслеживает глубину рекурсии, если она вам понадобится при выравнивании.
Это выведет:

$array = array( 
    'A' => array('B' => array( 1, 2, 3)), 
    'C' => array(4, 5) 
); 
print_r(array_flatten_recursive($array)); 

#Returns: 
Array ( 
    [0] => 1 
    [1] => 2 
    [2] => 3 
    [3] => 4 
    [4] => 5 
)
5
SamGoody

В PHP 7 вы можете использовать генераторы и делегирование генераторов (yield from) для выравнивания массива:

function array_flatten_iterator (array $array) {
    foreach ($array as $value) {
        if (is_array($value)) {
            yield from array_flatten_iterator($value);
        } else {
            yield $value;
        }
    }
}

function array_flatten (array $array) {
    return iterator_to_array(array_flatten_iterator($array), false);
}

Пример:

$array = [
    1,
    2,
    [
        3,
        4,
        5,
        [
            6,
            7
        ],
        8,
        9,
    ],
    10,
    11,
];    

var_dump(array_flatten($array));

http://3v4l.org/RU30W

4
kelunik

В PHP> = 5.3 и на основании ответа Люка М (первого) вы можете использовать замыкания, подобные этому

array_walk_recursive($aNonFlat, function(&$v, $k, &$t){$t->aFlat[] = $v;}, $objTmp);

Мне это нравится, потому что мне не нужно заключать код функции в кавычки, как при использовании create_function ()

4
hisa_py

Нерекурсивное решение (но разрушающее порядок):

function flatten($ar) {
    $toflat = array($ar);
    $res = array();

    while (($r = array_shift($toflat)) !== NULL) {
        foreach ($r as $v) {
            if (is_array($v)) {
                $toflat[] = $v;
            } else {
                $res[] = $v;
            }
        }
    }

    return $res;
}
4
phihag

Если у вас есть массив массивов, который не превышает глубину более одного уровня (пример использования, который я нахожу распространенным), вы можете обойтись без array_merge и оператора splat.

<?php

$notFlat = [[1,2],[3,4]];
$flat = array_merge(...$notFlat);
var_dump($flat);

Результат:

array(4) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
}

Оператор splat эффективно изменяет массив массивов на список массивов в качестве аргументов для array_merge.

2
Josh Johnson

Использование функций высшего порядка (примечание: я использую встроенные анонимные функции , которые появились в PHP 5.3): 

function array_flatten($array) {
    return array_reduce(
        $array,
        function($prev, $element) {
            if (!is_array($element))
                $prev[] = $element;
            else
                $prev = array_merge($prev, array_flatten($element));
            return $prev;
        },
        array()
    );
}
2
Paul d'Aoust

Если вы в порядке с потерей ключей массива, вы можете сгладить многомерный массив, используя рекурсивное замыкание в качестве обратного вызова, который использует array_values ​​(), убедившись, что этот обратный вызов является параметром для array_walk (), следующим образом.

<?php  

$array = [1,2,3,[5,6,7]];
$nu_array = null;
$callback = function ( $item ) use(&$callback, &$nu_array) {
    if (!is_array($item)) {
    $nu_array[] = $item;
    }
    else
    if ( is_array( $item ) ) {
     foreach( array_values($item) as $v) {
         if ( !(is_array($v))) {
             $nu_array[] = $v;
         }
         else
         { 
             $callback( $v );
         continue;
         }    
     }
    }
};

array_walk($array, $callback);
print_r($nu_array);

Один недостаток предыдущего примера заключается в том, что он включает в себя написание гораздо большего количества кода, чем в следующем решении, которое использует array_walk_recursive () вместе с упрощенным обратным вызовом:

<?php  

$array = [1,2,3,[5,6,7]];

$nu_array = [];
array_walk_recursive($array, function ( $item ) use(&$nu_array )
                     {
                         $nu_array[] = $item;
                     }
);
print_r($nu_array);

Смотрите живой код

Этот пример кажется предпочтительнее предыдущего, скрывая подробности о том, как значения извлекаются из многомерного массива. Конечно, итерация происходит, но влечет ли она за собой рекурсию или управляющую структуру (структуры), вы узнаете только из прочтения array.c. Поскольку функциональное программирование фокусируется на вводе и выводе, а не на мелочах получения результата, несомненно, можно не беспокоиться о том, как происходит закулисная итерация, то есть до тех пор, пока перспективный работодатель не задаст такой вопрос. 

1
slevy1
/*consider $mArray as multidimensional array and $sArray as single dimensional array
this code will ignore the parent array
*/

function flatten_array2($mArray) {
    $sArray = array();

    foreach ($mArray as $row) {
        if ( !(is_array($row)) ) {
            if($sArray[] = $row){
            }
        } else {
            $sArray = array_merge($sArray,flatten_array2($row));
        }
    }
    return $sArray;
}
1
Iman

Новый подход, основанный на функции предыдущего примера, представленной хаосом, которая исправляет ошибку перезаписи строковых ключей в мульти-массивах:

# Flatten a multidimensional array to one dimension, optionally preserving keys.
# $array - the array to flatten
# $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys
# $out - internal use argument for recursion

function flatten_array($array, $preserve_keys = 2, &$out = array(), &$last_subarray_found) 
{
        foreach($array as $key => $child)
        {
            if(is_array($child))
            {
                $last_subarray_found = $key;
                $out = flatten_array($child, $preserve_keys, $out, $last_subarray_found);
            }
            elseif($preserve_keys + is_string($key) > 1)
            {
                if ($last_subarray_found)
                {
                    $sfinal_key_value = $last_subarray_found . "_" . $key;
                }
                else
                {
                    $sfinal_key_value = $key;
                }
                $out[$sfinal_key_value] = $child;
            }
            else
            {
                $out[] = $child;
            }
        }

        return $out;
}

Example:
$newarraytest = array();
$last_subarray_found = "";
$this->flatten_array($array, 2, $newarraytest, $last_subarray_found);
1
xtrm

вы можете попробовать это:

function flat_an_array($a)
{
    foreach($a as $i)
    {
        if(is_array($i)) 
        {
            if($na) $na = array_merge($na,flat_an_array($i));
            else $na = flat_an_array($i);
        }
        else $na[] = $i;
    }
    return $na;
}
1
TomSawyer

Я нашел простой способ конвертировать многоуровневый массив в один . Я использую функцию "http_build_query", которая преобразует массив в строку URL-адреса . Затем разделите строку с помощью разнесения и декодируйте значение.

Вот образец.

$converted = http_build_query($data);
$rows = explode('&', $converted);
$output = array();
foreach($rows AS $k => $v){
   list($kk, $vv) = explode('=', $v);
   $output[ urldecode($kk) ] =  urldecode($vv);
}
return $output;
0
SequenceDigitale.com

Простой подход .. Посмотрите это через рекурсию ..

<?php

function flatten_array($simple){
static $outputs=array();
foreach ( $simple as $value)
{
if(is_array($value)){
    flatten_array($value);
}
else{
    $outputs[]=$value;
}

}
return $outputs;
}

$eg=['s'=>['p','n'=>['t']]];
$out=flatten_array($eg);
print_r($out);

?>
0
Paras Agarwal

Вы можете использовать функцию flatten из Нестандартной библиотеки PHP (NSPL) . Работает с массивами и любыми повторяемыми структурами данных.

assert([1, 2, 3, 4, 5, 6, 7, 8, 9] === flatten([[1, [2, [3]]], [[[4, 5, 6]]], 7, 8, [9]]));
0
Ihor Burlachenko