How to "Flatten" a Multi-Dimensional Array to Simple One in PHP

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

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

?>

Tested with PHP 5.5.9-1ubuntu4.24 (cli) (built: Mar 16 2018 12:32:06)

How to Flatten a Multidimensional Array?

You can use the Standard PHP Library (SPL) to "hide" the recursion.

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($a));
foreach($it as $v) {
echo $v, " ";
}

prints

1 2 3 4 5 6 7 8 9 

Convert multidimensional array into single array

Assuming this array may or may not be redundantly nested and you're unsure of how deep it goes, this should flatten it for you:

function array_flatten($array) { 
if (!is_array($array)) {
return FALSE;
}
$result = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
$result = array_merge($result, array_flatten($value));
}
else {
$result[$key] = $value;
}
}
return $result;
}

PHP multidimensional array to flatten WITH KEYS

You can write a recursive function for that:

$nested = array(
'Orange',
'Grape',
'Banana' => array(
'Big',
'Small'
),
'Apple' => array(
'Red',
'Green' => array(
'Soft',
'Hard'
)
)
);

function flattern($array)
{
$flat=[];
foreach($array as $key=>$val){
if(is_array($val)){
$flat[]=$key;
$flat = array_merge($flat, flattern($val));
}else{
$flat[]=$val;
}
}
return $flat;
}

var_dump(flattern($nested));

How can I flatten a simple array without writing a loop operator explicitly?

You could map it:

$arr = array_map(function($element) {
return $element['id'];
}, $arr);

Since array_map probably internally loops, you could do it truly without looping:

$arr = array_reduce($arr, function($arr, $element) {
$arr[] = $element['id'];
return $arr;
});

But there's no reason to not loop. There's no real performance gain, and the readability of your code is arguably decreased.

How to 'flatten' a multi dimensional array of unknown depth and length AND record it's parent-child relations?

This can be achieved with a recursive function that pushes all the items from a given level of the array, then calls itself for any children arrays:

function list_items($array, $parent = 0) {
$output = array();
foreach ($array as $arr) {
$output[] = array('id' => $arr['id'], 'name' => $arr['name'], 'parent' => $parent);
if (is_array($arr['children'] ?? NULL)) {
$output = array_merge($output, list_items($arr['children'], $arr['id']));
}
}
return $output;
}

$items = list_items($array);

Output (for my slightly expanded data):

Array
(
[0] => Array
(
[id] => 2
[name] => Item2
[parent] => 0
)
[1] => Array
(
[id] => 1
[name] => Item1
[parent] => 2
)
[2] => Array
(
[id] => 5
[name] => Item5
[parent] => 1
)
[3] => Array
(
[id] => 4
[name] => Item4
[parent] => 2
)
[4] => Array
(
[id] => 3
[name] => Item3
[parent] => 0
)
)

Demo on 3v4l.org

Update

It turns out that there is an inconsistency in the array structure; when there is only one child, only the child value is stored rather than a single element array. This can be dealt with by checking the the array to see if the id (Ид) element is set, and if it is, pushing the array one level deeper before processing:

function list_items($array, $parent = 0) {
$output = array();
if (isset($array['Ид'])) {
$array = array($array);
}
foreach ($array as $arr) {
if (!is_array($arr)) echo $arr;
$output[] = array('id' => $arr['Ид'], 'name' => $arr['Наименование'], 'parent' => $parent);
if (is_array($arr['Группы']['Группа'] ?? NULL)) {
$output = array_merge($output, list_items($arr['Группы']['Группа'], $arr['Ид']));
}
}
return $output;
}

$items = list_items($array);
print_r($items);

Demo on 3v4l.org

PHP: How to flatten a multidimensional array by duplicate values

Since keys must be unique, you can index on the label and you will only have one of each:

$result = array_column($array, null, 'label');

If you just want a single dimension with unique values, extract all labels and then make it unique:

$result = array_unique(array_column($array, 'label'));

If this array is coming from a database query then you would do it in the query instead.



Related Topics



Leave a reply



Submit