从多维数组中获取所有的值

5

假设我有一个这样的数组:

$array = [
    'car' => [
        'BMW' => 'blue',
        'toyota' => 'gray'
        ],
    'animal' => [
        'cat' => 'orange',
        'horse' => 'white'
        ]
    ];

接下来,我想获取所有值(颜色'blue''gray''orange''white'),并将它们合并成一个数组。如何在不使用两个foreach循环的情况下实现?

提前致谢。


编写一个函数,其中使用两次 for-each,然后只需调用该函数。 - Jonny Henly
我知道,但是每次调用它会不会影响性能呢? - Vaivez66
我对PHP并不是非常熟悉,所以我不知道是否有内置函数可以实现您想要的功能而不使用嵌套for循环。除非确实有明显的问题,否则不必担心遍历两个数组。过早优化是万恶之源。 - Jonny Henly
好的...说实话,我也不熟悉... - Vaivez66
SPL递归迭代器 http://php.net/manual/zh/class.recursivearrayiterator.php 参见:https://dev59.com/qnM_5IYBdhLWcg3wlEFH - ArtisticPhoenix
另一个选项是将原始数组展平。在这种情况下,对象非常不同,但如果两个对象都是汽车,例如:$array = [ 'car_BMW' => 'blue', 'car_toyota' =>'gray' ]; - WSimpson
7个回答

7

简述

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

来源: 如何在PHP中将多维数组“展平”成简单的一维数组?

对于您的使用情况,您应该像这样使用它:

<?php
$array = [
    'car' => [
        'BMW' => 'blue',
        'toyota' => 'gray'
        ],
    'animal' => [
        'cat' => 'orange',
        'horse' => 'white'
        ]
    ];
$result = call_user_func_array('array_merge', $array);
$result = array_values($result);

//$result = ['blue', 'gray', 'orange', 'white']

这很有趣,但并不能获取所有的值。我的意思是它只能获取第二层的值。所以如果有的话,甚至不包括第一层。 - cottton
@cottton 的回复有点晚,但是他说的没错,这个解决方案只适用于获取第二层的值。如果你需要同时获取第一层和第二层的值,我建议你使用 for 循环,因为这可能太复杂了,无法用一行代码实现。祝好! - Ng Sek Long
如果您在PHP8上遇到“array_merge()不接受未知的命名参数”错误,请查看此答案https://dev59.com/ksLra4cB1Zd3GeqPGU68 - Nuryagdy Mustapayev

3

我看到的旧函数并不适用于所有情况,以下是常见的、经典的递归函数:

function getArrayValuesRecursively(array $array)
{
    $values = [];
    foreach ($array as $value) {
        if (is_array($value)) {
            $values = array_merge($values,
                getArrayValuesRecursively($value));
        } else {
            $values[] = $value;
        }
    }
    return $values;
}

示例数组:

$array = [
    'car'    => [
        'BMW'    => 'blue',
        'toyota' => 'gray'
    ],
    'animal' => [
        'cat'   => 'orange',
        'horse' => 'white'
    ],
    'foo'    => [
        'bar',
        'baz' => [
            1,
            2 => [
                2.1,
                'deep' => [
                    'red'
                ],
                2.2,
            ],
            3,
        ]
    ],
];

调用:

echo var_export(getArrayValuesRecursively($array), true) . PHP_EOL;

结果:

// array(
//     0 => 'blue',
//     1 => 'gray',
//     2 => 'orange',
//     3 => 'white',
//     4 => 'bar',
//     5 => 1,
//     6 => 2.1,
//     7 => 'red',
//     8 => 2.2,
//     9 => 3,
// )

1
谢谢你为我节省了时间! - Robert Moskal

1

试试这个:

function get_values($array){
    foreach($array as $key => $value){
        if(is_array($array[$key])){
            print_r (array_values($array[$key]));
        }
    }
}

get_values($array);

1

如何在不使用两次foreach的情况下完成这个操作?

首先使用RecursiveIteratorIterator类来展开多维数组,然后应用array_values()函数以获取单个数组中所需的颜色值。

以下是参考文献:

因此,您的代码应该像这样:

$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
$flatten_array = array_values(iterator_to_array($iterator,true));

// display $flatten_array
echo "<pre>"; print_r($flatten_array);

这里是实时演示的链接。

有趣,但不适用于“混合”数组。一旦你在一个数组中得到一个值,在另一个数组中该方法就会“忽略”那个值。例如数组:['foo' => ['bar', 'baz' => [1, 2, 3]]] - cottton

1
这是一个递归函数,可以让您获得这些端点值的数组,或者获得一个带有所有键但已被压扁的数组。
代码:
<?php

$array = [
    'car' => [
        'BMW' => 'blue',
        'toyota' => 'gray'
        ],
    'animal' => [
        'cat' => 'orange',
        'horse' => 'white'
        ]
    ];

//
print "\n<br> Array (Original): ".print_r($array,true);
print "\n<br> Array (Flattened, With Keys): ".print_r(FlattenMultiArray($array,true),true);
print "\n<br> Array (Flattened, No Keys): ".print_r(FlattenMultiArray($array,false),true);

//
function FlattenMultiArray($array,$bKeepKeys=true,$key_prefix='')
{
    //
    $array_flattened=Array();

    //
    foreach($array as $key=>$value){

        //
        if(Is_Array($value)){
            $array_flattened=Array_Merge(
                $array_flattened,
                FlattenMultiArray($value,$bKeepKeys,$key)
            );
        }
        else{
            if($bKeepKeys){
                $array_flattened["{$key_prefix}_{$key}"]=$value;
            }
            else{
                $array_flattened[]=$value;
            }
        }
    }

    return $array_flattened;
}

?>

输出:

<br> Array (Original): Array
(
    [car] => Array
        (
            [BMW] => blue
            [toyota] => gray
        )

    [animal] => Array
        (
            [cat] => orange
            [horse] => white
        )

)

<br> Array (Flattened, With Keys): Array
(
    [car_BMW] => blue
    [car_toyota] => gray
    [animal_cat] => orange
    [animal_horse] => white
)

<br> Array (Flattened, No Keys): Array
(
    [0] => blue
    [1] => gray
    [2] => orange
    [3] => white
)

如果我们的数组深度超过1,那么展平操作怎么处理? - Deadpool

0
如果您不关心索引,那么这应该可以解决问题:
$colors = array();
foreach ($array as $item) {
  $colors = array_merge($colors, array_values($item));
}

如果你想保留索引,你可以使用:
$colors = array();
foreach ($array as $item) {
  // this leaves you open to elements overwriting each other depending on their keys
  $colors = array_merge($colors, $item);
}

希望这能有所帮助。


0

这个怎么样?它可以处理任何数组深度。

private function flattenMultiArray($array)
{
    $result = [];
    self::flattenKeyRecursively($array, $result, '');

    return $result;
}

private static function flattenKeyRecursively($array, &$result, $parentKey)
{
    foreach ($array as $key => $value) {
        $itemKey = ($parentKey ? $parentKey . '.' : '') . $key;
        if (is_array($value)) {
            self::flattenKeyRecursively($value, $result, $itemKey);
        } else {
            $result[$itemKey] = $value;
        }
    }
}

顺便说一句,这个解决方案不是我自己的,但非常完美地工作,我希望它能帮助到某些人。

https://github.com/letsdrink/ouzo/blob/master/src/Ouzo/Goodies/Utilities/Arrays.php


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接