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
How to Get File_Get_Contents() to Work With Https
How to Prevent Duplicate Usernames When People Register
Simplexml: Selecting Elements Which Have a Certain Attribute Value
Bind Multiple Parameters into MySQLi Query
Reference: Why Are My "Special" Unicode Characters Encoded Weird Using Json_Encode
How to Get Numeric Types from MySQL Using Pdo
Undefined Function MySQL_Connect()
PHP Error: "Cannot Pass Parameter 2 by Reference"
Access Array Returned by a Function in PHP
How to Reindex an Array in PHP But With Indexes Starting from 1
Matching Unicode Letter Characters in Pcre/PHP
What Does the Variable $This Mean in PHP
When Do I Use the PHP Constant "PHP_Eol"
Difference Between Http_Host and Server_Name in PHP