也许这是一个愚蠢的问题,但我无法意识到是否有可能在没有递归的情况下展平多维数组?
我有一个由递归写的解决方案:
function transform (arr) {
var result = [];
arr.forEach(flatten)
function flatten (el) {
if (Array.isArray(el)) {
return el.forEach(flatten);
}
return result.push(el);
}
return result;
}
要展平的数组示例:
[1, {a: [2, 3]}, 4, [5, [6]], [[7], 8, 9], 10]
执行:
var a = [1, {a: [2, 3]}, 4, [5, [6]], [[7], 8, 9], 10];
var r = transform(r);
console.log(r); // [1, {a: [2, 3]}, 4, 5, 6, 7, 8, 9, 10]
谢谢!
答案 0 :(得分:4)
您可以使用堆栈。当您发现嵌套数组时,只需将其替换为其项目。
function flatten(arr) {
var result = [];
var stack = arr, first;
while (stack.length > 0) {
first = stack[0];
if (Array.isArray(first)) {
// Replace the nested array with its items
Array.prototype.splice.apply(stack, [0, 1].concat(first));
} else {
result.push(first);
// Delete the first item
stack.splice(0, 1);
}
}
return result;
}
答案 1 :(得分:1)
你必须通过其他方式管理国家。
这里我用数组做。它让我们可以跟踪我们在整体方案中所处的位置。我觉得我这样做相当没有吸引力,但工作已经完成。
function transform(arr){
var state = [];
var i = 0,
a = arr;
var result = [];
while(true){
var val = a[i];
if(Array.isArray(val)){
state.push({i: i, a: a});
a = val;
i = -1;
} else if (val !== undefined) {
result.push(val)
}
if(i++ >= a.length - 1){
if(state.length > 0)
{
var s = state.pop();
a = s.a;
i = s.i + 1;
} else {
break;
}
}
}
return result;
}
var a = [1, {a: [2, 3]}, 4, [5, [6]], [[7], 8, 9], 10];
console.log(a); // Chrome Outputs: [1, Object, 4, Array[2], Array[3], 10]
var r = transform(a);
console.log(r); // Chrome Outputs: [1, Object, 4, 5, 6, 7, 8, 9, 10]
答案 2 :(得分:1)
我在采访中得到了完全相同的问题,并提出了这个解决方案:
function flattenNonRecursion(arr) {
const res = arr.slice();
let i = 0;
while (i < res.length) {
if (Array.isArray(res[i])) {
res.splice(i, 1, ...res[i]);
}
else {
i++;
}
}
return res;
}
console.log(flattenNonRecursion([1, {a: [2, 3]}, 4, [5, [6]], [[7], 8, 9], 10]));
// [1, {a: [2, 3]}, 4, 5, 6, 7, 8, 9, 10]
所以,主要的想法是我们正在向前推进我们的数组,如果我们遇到一个数组,我们用它的内容替换它并继续前进......这个解决方案的复杂性是O(n)。
答案 3 :(得分:1)
这里是O(N)解,其中N是展平数组中的项目数,而不会改变输入数组。
当我们使用堆栈时,似乎更自然地使用pop和push。此解决方案不使用非常昂贵的剪接,不移位,移位和其他就地数组变异方法。
虽然不是必须的,但可以使用apply
来代替使用ES6扩展运算符。
function flat(input) {
const stack = [...input];
const res = [];
while (stack.length) {
// pop value from stack
const next = stack.pop();
if (Array.isArray(next)) {
// push back array items, won't modify the original input
stack.push(...next);
} else {
res.push(next);
}
}
return res.reverse();
}
答案 4 :(得分:0)
这是一个使用两个数组来压扁另一个数组的提案。
基本上一个数组将计数保持在某个水平,另一个数组保持对具有该级别的数组的引用。
与其他两个解决方案相比的主要优势是单独使用Array#push而没有其他类似的数据删除方法。
function transform(array) {
var result = [],
level = 0,
reference = [array],
counter = [0];
while (level >= 0) {
if (counter[level] >= reference[level].length) {
level--;
continue;
}
if (Array.isArray(reference[level][counter[level]])) {
reference[level + 1] = reference[level][counter[level]]
counter[level]++;
level++;
counter[level] = 0;
continue;
}
result.push(reference[level][counter[level]]);
counter[level]++;
}
return result;
}
var a = [1, { a: [2, 3] }, 4, [5, [6]], [[7], 8, 9], 10],
r = transform(a);
console.log(r);
&#13;
答案 5 :(得分:0)
我简化了@ Misha的解决方案:
function flatten(array) {
var result = [];
var stack = array
var item;
while (stack.length) {
item = stack.shift();
if (Array.isArray(item)) [].unshift.apply(stack, item);
else result.push(item);
}
return result;
}
答案 6 :(得分:0)
我们可以为此使用JS Array flat()
方法,截至2019年5月,除IE之外,大多数浏览器目前都支持该方法。
var newArray = arr.flat([depth]);
深度:可选
指定嵌套数组结构应展平的深度级别。默认为1。
const arr1 = [1, 2, [3, 4]]
const flattenArr = arr1.flat()
console.log(flattenArr)
// [1, 2, 3, 4]
const arr2 = [1, 2, [3, 4, [5, 6]]];
const flattenArr = arr2.flat(2) // <== using 2 here
console.log(flattenArr)
// [1, 2, 3, 4, [5, 6]]
const arr3 = [1, {a: [2, 3]}, 4, [5, [6]], [[7], 8, 9], 10]
// Using `Infinity` here to flatten any depth level array
// For this use case we could have also used 3 here
const flattenArr = arr3.flat(Infinity)
console.log(flattenArr)
// [1, {a: [2, 3]}, 4, 5, 6, 7, 8, 9, 10]
.as-console-wrapper { max-height: 100%!important; }