如何在PHP中将多维数组"扁平化"为简单数组?

Adr*_*ana 73 php arrays multidimensional-array

这可能是初学者的问题,但我已经阅读了较长时间的文档,我找不到任何解决方案.我以为我可以为每个维度使用implode然后将这些字符串重新组合在一起str_split以创建新的简单数组.但是我永远不知道连接模式是否也不在值中,因此在执行之后str_split我的原始值可能会中断.

combine($array1, $array2)对于多维数组中的数组是否有类似的东西?

Pra*_*dra 121

$array  = your array

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

echo "<pre>";
print_r($result);
Run Code Online (Sandbox Code Playgroud)

参考: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);
Run Code Online (Sandbox Code Playgroud)

  • 从php5.3开始,您现在可以使用splat运算符:`$ result = array_merge(... $ array);`https://www.php.net/manual/zh/migration56.new-features.php#migration56。新功能 (6认同)

Arn*_*Roa 52

这是一条线,SUPER易于使用:

$result = array();
array_walk_recursive($original_array,function($v) use (&$result){ $result[] = $v; });
Run Code Online (Sandbox Code Playgroud)

在匿名函数/闭包中很容易理解.$v是你的价值$original_array.

  • 这是唯一一个在两级数组中为我工作的方法. (3认同)

Luc*_*c M 41

使用 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)
}
*/

?>
Run Code Online (Sandbox Code Playgroud)

用PHP 5.5.9-1ubuntu4.24(cli)测试(内置:2018年3月16日12:32:06)

  • 为什么这个答案提到使用`array_values()`?我根本看不到在答案中涉及的任何功能. (10认同)
  • @jskilski对象(本例中为`$ objTmp`)自动通过引用传递; 数组不是.尝试使用匿名函数(http://php.net/manual/en/functions.anonymous.php)而不是`create_function`. (2认同)

小智 19

// $array = your multidimensional array

$flat_array = array();

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

$flat_array[$k] = $v;

}
Run Code Online (Sandbox Code Playgroud)

还记录了:http: //www.phpro.org/examples/Flatten-Array.html

  • 注意:仅用于基元数组."RecursiveArrayIterator将所有对象视为拥有子对象,并尝试将它们递归到它们中." http://www.php.net/manual/en/class.recursivearrayiterator.php#106519 (2认同)
  • 我知道这是旧的但仍然有用,但是$ k需要被一些独特的东西取代,例如计数器.如果内部数组中的名称与主要名称相同,则仅使用$ k会导致元素被删除. (2认同)

Jos*_*son 15

如果您特别有一个数组数组,其深度不超过一个级别(我发现一个用例很常见),您可以使用array_mergesplat 运算符。

<?php

$notFlat = [[1,2],[3,4]];
$flat = array_merge(...$notFlat);
var_dump($flat);
Run Code Online (Sandbox Code Playgroud)

输出:

array(4) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
}
Run Code Online (Sandbox Code Playgroud)

splat 运算符有效地将数组数组更改为数组列表作为 的参数array_merge


kel*_*nik 6

在 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);
}
Run Code Online (Sandbox Code Playgroud)

例子:

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

var_dump(array_flatten($array));
Run Code Online (Sandbox Code Playgroud)

http://3v4l.org/RU30W


pet*_*zek 6

抱歉对 necrobumping,但提供的答案都没有做我直觉上理解的“扁平化多维数组”。即这种情况:

[
  'a' => [
    'b' => 'value',
  ]
]
Run Code Online (Sandbox Code Playgroud)

所有提供的解决方案都会将其展平为 just ['value'],但这会丢失有关密钥和深度的信息,此外,如果您在其他地方还有另一个 'b' 密钥,它将覆盖它们。

我想得到这样的结果:

[
  'a_b' => 'value',
]
Run Code Online (Sandbox Code Playgroud)

array_walk_recursive 不传递有关它当前递归的密钥的信息,所以我只用简单的递归来完成它:

function flatten($array, $prefix = '') {
    $return = [];
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            $return = array_merge($return, flatten($value, $prefix . $key . '_'));
        } else {
            $return[$prefix . $key] = $value;
        }
    }
    return $return;
}
Run Code Online (Sandbox Code Playgroud)

根据您的喜好修改 $prefix 和 '_' 分隔符。

游乐场在这里:https : //3v4l.org/0B8hf


phi*_*hag 5

非递归解决方案(但破坏顺序):

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;
}
Run Code Online (Sandbox Code Playgroud)


cha*_*aos 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;
}
Run Code Online (Sandbox Code Playgroud)


Sam*_*ody 5

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;
}
Run Code Online (Sandbox Code Playgroud)

这种方法的最大好处是它可以跟踪递归的深度,如果在展平时需要它.
这将输出:

$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 
)
Run Code Online (Sandbox Code Playgroud)

  • 注意:仅用于基元数组."RecursiveArrayIterator将所有对象视为拥有子对象,并尝试将它们递归到它们中." http://www.php.net/manual/en/class.recursivearrayiterator.php#106519 (3认同)