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

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

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

Ответ 1

Использовать 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)

Ответ 2

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

Другой метод из 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 
)

Ответ 7

Нерекурсивное решение (но уничтожение порядка):

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

Ответ 8

В PHP >= 5.3 и на основе ответа Luc M (первый) вы можете использовать блокировки вроде этого

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

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

Ответ 9

С 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

Ответ 10

Использование функций более высокого порядка (примечание: я использую встроенные анонимные функции, которые появились в 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()
    );
}

Ответ 11

Если вы справитесь с потерями ключей массива, вы можете сгладить многомерный массив, используя рекурсивное закрытие в качестве обратного вызова, который использует 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. Поскольку функциональное программирование фокусируется на вводных и выходных данных, а не на мелочи получения результата, безусловно, можно не беспокоиться о том, как происходит итерация за кадром, то есть до тех пор, пока перспективный работодатель не поставит такой вопрос.

Ответ 12

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

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

Ответ 13

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

Ответ 14

вы можете попробовать следующее:

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

Ответ 15

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

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

Ответ 16

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

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

?>

Ответ 17

Если у вас есть массив массивов, который не превышает глубину более одного уровня (пример использования, который я нахожу распространенным), вы можете обойтись без 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 массив массивов на список массивов в качестве аргументов для array_merge.

Ответ 18

Я нашел простой способ конвертировать многоуровневый массив в один. Я использую функцию "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;

Ответ 19

Если вам интересны только значения для одного конкретного ключа, вы можете найти этот подход полезным:

function valuelist($array, $array_column) {
    $return = array();
    foreach($array AS $row){
        $return[]=$row[$array_column];
    };
    return $return;
};

Пример:

Учитывая $get_role_action =

array(3) {
  [0]=>
  array(2) {
    ["ACTION_CD"]=>
    string(12) "ADD_DOCUMENT"
    ["ACTION_REASON"]=>
    NULL
  }
  [1]=>
  array(2) {
    ["ACTION_CD"]=>
    string(13) "LINK_DOCUMENT"
    ["ACTION_REASON"]=>
    NULL
  }
  [2]=>
  array(2) {
    ["ACTION_CD"]=>
    string(15) "UNLINK_DOCUMENT"
    ["ACTION_REASON"]=>
    NULL
  }
}

чем $variables['role_action_list']=valuelist($get_role_action, 'ACTION_CD'); приведет к:

$variables["role_action_list"]=>
  array(3) {
    [0]=>
    string(12) "ADD_DOCUMENT"
    [1]=>
    string(13) "LINK_DOCUMENT"
    [2]=>
    string(15) "UNLINK_DOCUMENT"
  }

Оттуда вы можете выполнять поиск значений следующим образом:

if( in_array('ADD_DOCUMENT', $variables['role_action_list']) ){
    //do something
};

Ответ 20

любой из них не работал у меня... так и пришлось запускать его сам. отлично работает:

function arrayFlat($arr){
$out = '';
    foreach($arr as $key => $value){

        if(!is_array($value)){
            $out .= $value.',';
        }else{
            $out .= $key.',';
            $out .= arrayFlat($value);
        }

    }
    return trim($out,',');
}


$result = explode(',',arrayFlat($yourArray));
echo '<pre>';
print_r($result);
echo '</pre>';

Ответ 21

Учитывая многомерный массив и преобразование его в одномерный, можно сделать, сняв все значения, которые имеют массивы и сохраняют их в первом измерении, например:

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