Get all values from multidimensional array
Asked Answered
H

8

5

Let's say, I have an array like this:

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

Then, I want to get all the values (the colour, 'blue', 'gray', 'orange', 'white') and join them into a single array. How do I do that without using foreach twice?

Thanks in advance.

Healy answered 29/6, 2016 at 2:42 Comment(6)
Write a function that uses for-each twice, then just call that function.Ftlb
I have, but won't that affect to the performance every time I call it?Healy
I'm not incredibly familiar with PHP, so I don't know if there is a built-in function that can achieve what you want and doesn't use nested for loops. I wouldn't worry about iterating over two arrays unless it's actually noticeable. Premature optimization is the root of all evil.Ftlb
Okay... To be honest, I'm not familiar either...Healy
SPL Recursive Iterator php.net/manual/en/class.recursivearrayiterator.php SEE: #1320403Alkali
Another option is to flatten the original array. In this case the objects are very dissimilar, but if both objects were cars for example: $array = [ 'car_BMW' => 'blue', 'car_toyota' =>'gray' ];Ashy
I
1

Try this:

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

get_values($array);
Implead answered 29/6, 2016 at 2:53 Comment(0)
F
7

TL;DR

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

Credit: How to "flatten" a multi-dimensional array to simple one in PHP?

In your use case, you should use it like this:

<?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']
Forecourt answered 26/7, 2019 at 7:36 Comment(3)
This is interesting, but does not get all values. I mean it only get 2nd level values. So not even 1st level (if there are any).Revolt
@Revolt was a bit late on the response, but yes this solution only works if you are getting 2nd level values. I suggest you just use a for loop if you are going both 1st and 2nd level value, since it probably is too complex for any one-liner, cheers!Forecourt
if you face error array_merge() does not accept unknown named parameters on PHP8 check this answer https://mcmap.net/q/1117041/-uncaught-argumentcounterror-array_merge-does-not-accept-unknown-named-parameters/4896948Saltation
R
4

Old but as far i see not really a "working on all cases" function posted.

So here is the common classic recursively function:

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

Example array:

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

Call:

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

Result:

// array(
//     0 => 'blue',
//     1 => 'gray',
//     2 => 'orange',
//     3 => 'white',
//     4 => 'bar',
//     5 => 1,
//     6 => 2.1,
//     7 => 'red',
//     8 => 2.2,
//     9 => 3,
// )
Revolt answered 5/4, 2021 at 17:33 Comment(2)
Thanks for saving me some time!Whallon
Very useful! In a case where I happened to know that all the keys would be unique (Advanced Custom Fields in WordPress), it was easy to convert this to retrieve the keys as wellFreewheel
A
4
array_merge(...array_values($columns))
Alber answered 5/9 at 9:5 Comment(1)
Perfect one-liner for my simple 2-level array, thanks!Stokowski
I
1

Try this:

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

get_values($array);
Implead answered 29/6, 2016 at 2:53 Comment(0)
N
1

How do I do that without using foreach twice?

First use RecursiveIteratorIterator class to flatten the multidimensional array, and then apply array_values() function to get the desired color values in a single array.

Here are the references:

So your code should be like this:

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

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

Here's the live demo

Nightly answered 29/6, 2016 at 2:54 Comment(1)
Interesting, but does not work with "mixed" arrays. As soon you got in one array a values and another array the method is "ignoring" the value in that one. Example array: ['foo' => ['bar', 'baz' => [1, 2, 3]]]Revolt
C
1

Here's a recursive function that gives you both the ability to get an array of those endpoint values, or to get an array with all keys intact, but just flattened.

Code:

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

?>

Outputs:

<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
)
Cub answered 29/6, 2016 at 2:55 Comment(1)
what about flatten if we have array depth more than 1?Eisegesis
L
0

If you don't care about the indexes, then this should do it:

$colors = array();
foreach ($array as $item) {
  $colors = array_merge($colors, array_values($item));
}

If you want to keep the indexes you could use:

$colors = array();
foreach ($array as $item) {
  // this leaves you open to elements overwriting each other depending on their keys
  $colors = array_merge($colors, $item);
}

I hope this helps.

Langille answered 29/6, 2016 at 2:53 Comment(0)
E
0

what about this one?It works with ANY array depth.

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

P.S. solution is not mine, but works perfectly, and I hope it will help someone. Original source:

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

Eisegesis answered 17/11, 2020 at 12:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.