### 從嵌套數組中提取子數組

#### [英]Extract child arrays from nested arrays

I have nested array data and I would like to extract all nested arrays to be siblings of their parent. I am pretty close, but I am getting an extra empty array in the results and I cannot figure out where it is coming from or how to get rid of it.

Note: I would really like to understand why this is happening and how to get rid of it in my function, and not just a `.filter(arr => arr.length)` on my results list.

This is my attempt so far:

``````var arrs = [
[1, 2, [3, 4], 5],
[6, [7, 8, 9, [10, 11]]],
[12, 13],
[[14, 15], [16, 17]],
[[1], 4, [1, 1], 4]
];

// Desired Output
// [
//   [1, 2, 5],
//   [3, 4],
//   [6],
//   [7, 8, 9],
//   [10, 11],
//   [12, 13],
//   [14, 15],
//   [16, 17],
//   [4, 4]
//   [1]
//   [1, 1]
// ]

function extractArrays (arr) {
return arr.reduce((res, curr) => {
if (Array.isArray(curr)) {
res = res.concat(extractArrays(curr));
}
else {
res[0].push(curr);
}
return res;
}, [[]]);
}

console.log(extractArrays(arrs));
// Results:
// [
//   [],  <-- Where is this coming from?
//   [ 1, 2, 5 ],
//   [ 3, 4 ],
//   [ 6 ],
//   [ 7, 8, 9 ],
//   [ 10, 11 ],
//   [ 12, 13 ],
//   [],  <-- Also here
//   [ 14, 15 ],
//   [ 16, 17 ],
//   [ 4, 4 ],
//   [ 1 ],
//   [ 1, 1 ]
// ]``````
``````.as-console-wrapper {
max-height: 100% !important;
}``````

## 5 个解决方案

### #1

4

Element like `[[14, 15], [16, 17]]` will introduce a `[]` after recursion. This should be handled by checking length.

``````var arrs = [
[1, 2, [3, 4], 5],
[6, [7, 8, 9, [10, 11]]],
[12, 13],
[[14, 15], [16, 17]],
[[1], 4, [1, 1], 4]
];

function extractArrays (arr, acc=[]) {
if (arr.length == 0 ) return acc;
let pure = arr.filter(elm => !Array.isArray(elm));
if (pure.length > 0) {
acc.push(pure);
}

acc.concat(arr.filter(elm => Array.isArray(elm)).map(elm => extractArrays(elm, acc)));

return acc;
}

console.log(extractArrays(arrs));``````

### #2

4

You can try the following code

``````var arrs = [
[1, 2, [3, 4], 5],
[6, [7, 8, 9, [10, 11]]],
[12, 13],
[
[14, 15],
[16, 17]
[
[1], 4, [1, 1], 4
]
];

function extractArrays(arr) {
return arr.reduce((res, curr, i) => {
if (Array.isArray(curr)) {
res = res.concat(extractArrays(curr));
} else {
let index = 0;
for (let j = 0; j <= i; j++) {
if (!Array.isArray(arr[j])) {
res[index] ? res[index].push(curr) : res.push([curr]);
break;
} else {
index++;
}
}
}
return res;
}, []); // <-- no initial empty array inside here
}

console.log(extractArrays(arrs));``````

### #3

1

I just wanted to share my approach to this problem, I enjoyed trying to solve it, in my case I also passed an array to the `extractArrays` method, in order to make easier to capture and filter every array inside the `arrs` param.

``````let result = [];
extractArrays(arrs, result);
console.log(result);

function extractArrays(arr, result) {
let newResult = arr.reduce((acc, curr) => {
if (Array.isArray(curr)) {
extractArrays(curr, result);
} else {
acc.push(curr);
}

return acc;
}, []);

newResult.length && result.push(newResult);
}
``````

### #4

1

You can check it when you return from function. stackblitz

``````function extractArray(arr) {
const res = arr.reduce((res, curr) => {
if(!Array.isArray(curr)){
return [[...res[0], curr], ...res.slice(1)]
}
return [...res, ...extractArray(curr)]
}, [[]]);

return res[0].length ? res : res.slice(1);
}
``````

EDIT: More performant function (check stackblitz link)

``````function extractFaster(arr) {
let res = [0];
function recExtract(arr) {
let hasNonArrayElm = false;
let index = res.length -1;
arr.forEach(curr => {
if (!Array.isArray(curr)) {
hasNonArrayElm ? res[index].push(curr) : res.splice(index, 0, [curr]);
hasNonArrayElm = true;
return;
}
recExtract(curr);
});
}

recExtract(arr);
res.splice(-1, 1)
return res;
}
``````

### #5

0

In ES6 there is actually an experimental array method called `flat()`. As of the writing of this answer, it's only compatible with Chrome, but a polyfill might be worth looking into, because it's SO EASY!

``````const arr = [1, 2, [3, 4]]
arr.flat() // outputs [1, 2, 3, 4]
``````