扁平化多个嵌套数组的数组而不带递归 - javascript
Flatten array of multiple nested arrays without recursion - javascript
也许这是一个愚蠢的问题,但我无法意识到是否可以在没有递归的情况下展平多维数组?
我有一个我用递归编写的解决方案:
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]
谢谢!
您可以使用堆栈。当您发现嵌套数组时,只需将其替换为其项即可。
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;
}
面试中遇到了完全相同的问题,并提出了这个解决方案:
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)。
这里是 O(N) 解决方案,其中 N 是平展数组中的项目数,而不会改变输入数组。
对我来说,当我们使用堆栈时,使用弹出和推送似乎更自然。该解决方案不使用非常昂贵的拼接、取消移位、移位和其他就地阵列突变方法。
使用 ES6 点差运算符,虽然不是必须的,可以用 apply
代替。
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();
}
您必须通过其他方式管理状态。
在这里,我使用数组来做到这一点。它让我们跟踪我们在我们正在做的事情的整体计划中的位置。我觉得我做得相当没有吸引力,但工作已经完成。
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]
function flat(arr) {
for (let i= 0; i<arr.length; i++) {
const element = arr[i];
if (Array.isArray(element)) {
arr.splice(i, 1, ...element); // replaces arr[i] with its elements
}
}
return arr;
}
这是非递归 + 就地数组修改(不创建新数组)
简化了@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;
}
我们可以为此使用 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; }
这是一个使用两个数组来展平另一个数组的建议。
基本上,一个数组将计数保持在某个级别,另一个数组保留对具有级别的数组的引用。
与其他两种解决方案相比,主要优点是一次性使用 Array#push,而没有其他 Array 的变异方法。
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);
const flatten = (array) => {
const flattenedArray = []; // an empty array that all flattened elements will be in
while(array.length) { // while there are still elements in the array
const ele = array.shift(); // remove the first element
if(!Array.isArray(ele)) { // check if this element is not an array
flattenedArray.push(ele); // since it's not, just push it into the flattened array
continue; // continue to do this to all non arrays and ignore the rest of the code until...
};
array = [...ele,...array]; // you've found an array in your given array, now you get all the elements of the array you just found, with the rest operator, put them all into a new array, with the remaining elements of the main array at it's back with also the rest operator, make it equal to the original array
};
return flattenedArray; // return the flattened array
};
// This is less problematic and straight forward, because all the elements previously removed that are not arrays continue to leave the main array into the flattened array
const ar =[1,2,[3,[4,5,[6,7,[8,9]]]]]
function singleArray(ar) {
return ar.reduce((ac, cur) =>{
if(Array.isArray(cur)){
return [...ac, ...singleArray(cur)]
}
return [...ac, cur];
},[])
}
console.log(singleArray(ar))
const getFalttenArrayWithInArrayModification = (arr) => {
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
arr.splice(i, 1, ...arr[i]);
if (Array.isArray(arr[i]))
i--;
}
}
return arr;
}
const input = [[[[2,5],6], [4,5]], 5, [[4,5], 3, [9,8]]];
console.log(getFalttenArrayWithInArrayModification(input));
答案是对 Skay 答案几乎没有修改,因为这没有处理第一个替换元素是数组的用例。
- 数组在递归方法中设置为null
- 具有嵌套对象数组的 Javascript 对象的递归搜索函数
- Javascript-用于展开数组的递归/for循环
- 递归布尔和/或到数组的jison解析器
- 给定一个带有数字的数组,我如何编写一个递归函数,当 2 个元素加起来为一个目标时,它会在数组中查找索引
- 异步循环使用递归:如何访问推送数组数据
- javascript递归,按数组位置查找子级
- 数组JavaScript中的递归串联字符串
- 简单数组递归而不是while
- 在数组上递归达到最大调用大小
- 在JavaScript中,从一组数组递归地构建一个字典/嵌套对象
- Javascript 数组递归更改值
- 删除数组递归调用模式中的项
- 在JavaScript中从多级数组递归生成一级数组
- 过滤器数组递归查找父级
- 通过单个数组递归记录javascript中所有可能的排列
- 转换无序列表html
- 对json数组递归调用子列表
- 从javascript数组递归地构建一个树
- 从对象数组递归地创建JSON树结构
- 没有生成器的JavaScript数组递归