How to Flatten a Multidimensional Array

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 

Function for flatten a multi-dimensional array

The trick is that if an element of the input array is an array itself then you should "concat" the element's flattened items into the input array instead of pushing the entire array.

Here is a solution using "reduce" and "Array.isArray(...)" which are only available in newer browsers which support the later specification of ECMAScript 5.1th Edition:

function flatten(array) {
return array.reduce(function(memo, el) {
var items = Array.isArray(el) ? flatten(el) : [el];
return memo.concat(items);
}, []);
}

flatten([1,2,3]) // => [1,2,3]
flatten([[1,2,3],["a","b","c"],[1,2,3]]) // => [1,2,3,"a","b","c",1,2,3]
flatten([[[1,2,3]]]) // => [1, 2, 3]

How do I flatten a two-dimensional array with 3 entries in javascript?

You can use the built in array method .flat() to do this.

In your example

function flat(array) {
return array.flat()
}

Snippet

function flat(arr) {
return arr.flat()
}

console.log(flat([
[1, 2, 3],
[5, 7, 8],
[9, 4, 6]
]));

Flatten multi dimensional array in python 3

Since you're using Python 3, you can take advantage of yield from with a recursive function. It has been introduced in Python 3.3.

As a bonus, you can flatten arbitrary nested lists, tuples, sets or ranges:

test_list = [1, [1], [12, 'test', set([3, 4, 5])], 2, 3, ('hello', 'world'), [range(3)]]

def flatten(something):
if isinstance(something, (list, tuple, set, range)):
for sub in something:
yield from flatten(sub)
else:
yield something


print(list(flatten(test_list)))
# [1, 1, 12, 'test', 3, 4, 5, 2, 3, 'hello', 'world', 0, 1, 2]
print(list(flatten('Not a list')))
# ['Not a list']
print(list(flatten(range(10))))
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Here's another example with a debug line:

def flatten(something, level=0):
print("%sCalling flatten with %r" % (' ' * level, something))
if isinstance(something, (list, tuple, set, range)):
for sub in something:
yield from flatten(sub, level+1)
else:
yield something

list(flatten([1, [2, 3], 4]))
#Calling flatten with [1, [2, 3], 4]
# Calling flatten with 1
# Calling flatten with [2, 3]
# Calling flatten with 2
# Calling flatten with 3
# Calling flatten with 4

How to flatten 2D array to 1D array?

A simple for loop will do, it is not difficult, but will depend on the order in which you want to copy the values. For instance (based on the fact that in your example the arrays all have the same length):

int[] newArray = new int[3 * a.length];
int index = 0;
for (int n = 0; n < a.length; n++) {
newArray[index++] = a[n];
newArray[index++] = b[n];
newArray[index++] = c[n];
}

or (different order, a, b, c can be of different lengths):

int[] newArray = new int[a.length + b.length + c.length];
System.arraycopy(a, 0, newArray, 0, a.length);
System.arraycopy(b, 0, newArray, a.length, b.length);
System.arraycopy(c, 0, newArray, a.length + b.length, c.length);

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

Flatten a multidimensional vector in c++

Your code is unecessarily complicated due to manually managing the memory and manually passing sizes around. Both is obsolete when you use std::vector. Even if you do want a raw C-array as result you can nevertheless use a std::vector and later copy its contents to properly allocated C-array. I would use a recursive approach:

#include <vector>
#include <iostream>

template <typename E,typename X>
void unroll(const std::vector<E>& v,std::vector<X>& out){
std::cout << "unroll vector\n";
out.insert(out.end(), v.begin(), v.end());
}


template <typename V,typename X>
void unroll(const std::vector<std::vector<V>>& v,std::vector<X>& out) {
std::cout << "unroll vector of vectors\n";
for (const auto& e : v) unroll(e,out);
}


int main() {
std::vector<std::vector<std::vector<int>>> x;
std::vector<int> y;
x.push_back({{1,2,3},{4,5,6}});
x.push_back({{7,8,9}});
unroll(x,y);
for (const auto& e : y) std::cout << e << " ";
}

Output:

unroll vector of vectors
unroll vector of vectors
unroll vector
unroll vector
unroll vector of vectors
unroll vector
1 2 3 4 5 6 7 8 9

Is there a way of recursively accessing the vector elements without explicitly using the vector element access operator for each case.

A vectors elements are stored in contiguous memory, hence you can use pointer arithmetics via its data(). However, a std::vector<std::vector<int>> does not store the ints in contiguous memory. Only the inner vectors elements are stored contiguously while each inner vector allocates the elements on the heap "somewhere". There is no short cut to access x[0][0][0] without accessing x[0][0]. Actually I would suggest to reconsider if you want to use nested vectors in the first place.


PS: I was cheating a little ;). I would expect it to be more performant to first calculate the total size of out before pushing elements to it as you are doing in your code. For brevity it was left out from the above. It can be done with similar recursion as the above code. Instead of pusing to out you would accumulate some size until you reach the first non-vector element type. Then reserve enough space for out upfront and only then run the actual recursion that populates out.

Javascript: Flatten multidimensional array in place using recursion

Do the recursive flattening from the inside out. First call the flatten function on the array that you find, then move the contents of that (now flat) array into the parent array. Loop backwards through the array so that you don't have to adjust the loop variable for the items that are inserted.

As you know that the arrays that you insert are flat, you can use the splice method to replace an array with its items.

It works like this:

start with
[[[2, 3], 4], 5, [6, 7]]

flatten [6,7] (which is already flat) and insert:
[[[2, 3], 4], 5, 6, 7]

flatten [[2, 3], 4] recursively calls flatten [2,3] and inserts in that array:
[[2, 3, 4], 5, 6, 7]
then it inserts [2, 3, 4]:
[2, 3, 4, 5, 6, 7]

Code: