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 int
s 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:
function flatten(arr) { for (var i = arr.length - 1; i >= 0; i--) { if (arr[i].constructor === Array) { flatten(arr[i]); Array.prototype.splice.apply(arr, [i, 1].concat(arr[i])); } }}
var x = [[[2, 3], 4], 5, [6, 7]];
flatten(x);
// Show result in snippetdocument.write(JSON.stringify(x));
Related Topics
How to Use Two Foreach to Insert Data in Database
How to Add Dynamic Filter Using PHP MySQL Ajax
Convert Doc/Docx Files to Pdf Using PHP
How to Update Field to Add Value to Existing Value
Regex for Only Allowing Letters, Numbers, Space, Commas, Periods
How to Install Imagick/Imagemagick PHP Extension on Windows 7
Strip Null Values of Json Object
Php Fatal Error: Uncaught Pdoexception: Could Not Find Driver
How to Set Current Date as Default Value of an Input
I Have Three Columns, I Want to Combine Them All in One Main_Table
Add Space After Every 4Th Character
Displaying a Base64 Images from a Database Via PHP
Laravel 5.5 Error 500 in Cpanel Shared Hosting
How to Get the Values of Input Using PHP
How to Run a PHP Script in the Background After a Form Is Submitted
How to Set the Default Value of an Attribute on a Laravel Model