Javascript中第n个嵌套数组平坦化的迭代解法
有人能给我看一下下面问题的迭代解决方案吗?我递归地解决了这个问题,但却遇到了一个迭代的解决方案。(Facebook技术采访问题) 解决方案必须使用第n个嵌套数组元素(即,如果有人在上面的示例中修改数组值/位置,则该解决方案必须仍然有效) 递归解决方案:Javascript中第n个嵌套数组平坦化的迭代解法,javascript,arrays,function,Javascript,Arrays,Function,有人能给我看一下下面问题的迭代解决方案吗?我递归地解决了这个问题,但却遇到了一个迭代的解决方案。(Facebook技术采访问题) 解决方案必须使用第n个嵌套数组元素(即,如果有人在上面的示例中修改数组值/位置,则该解决方案必须仍然有效) 递归解决方案: var flatten = function(input) { var result = []; input.forEach(function(element) { result = result.concat(
var flatten = function(input) {
var result = [];
input.forEach(function(element) {
result = result.concat(Array.isArray(element) ? flatten(element) : element);
});
return result;
}
工作,但不建议:
var flatten = function(input) {
return eval("[" + JSON.stringify(input).
replace(/\[/g,"").replace(/\]/g,"") + "]");
}
不同的迭代算法:
function flatten2(input) {
var output = [];
var todo = [input];
var current;
var head;
while(todo.length) {
var current = todo.shift();
if(Array.isArray(current)) {
current = current.slice();
head = current.shift();
if(current.length) {
todo.unshift(current)
}
todo.unshift(head);
} else {
output.push(current);
}
}
return output;
}
function flatten(input) {
var output = [];
var todo = [input];
var current;
while(todo.length) {
var current = todo.shift();
if(Array.isArray(current)) {
todo.unshift.apply(todo, current)
} else {
output.push(current);
}
}
return output;
}
- 将所有元素放在堆栈上
- 当堆栈不为空时,删除第一个元素。
- 如果该元素是标量,则将其添加到输出中
- 如果该元素是数组,则将其拆分为head(第一个元素)和tail(其余元素),并将两者添加到堆栈中
var input = [1, {a: 2}, [3], [[4, 5], 6], 7];
function flatten(input) {
var i, placeHolder = [input], lastIndex = [-1], out = [];
while (placeHolder.length) {
input = placeHolder.pop();
i = lastIndex.pop() + 1;
for (; i < input.length; ++i) {
if (Array.isArray(input[i])) {
placeHolder.push(input);
lastIndex.push(i);
input = input[i];
i = -1;
} else out.push(input[i]);
}
}
return out;
}
flatten(input);
这同样更快(对于平面迭代来说),并且多次调用它的垃圾收集器问题更少。它的速度非常接近Chrome中的递归函数调用,比FireFox和IE中的递归快很多倍
我在这里重新创建了Tomalak的测试,因为旧的jsPerf已被破坏以进行编辑:这个怎么样
inp=[1,{a:2}[3],[4,5,6],7]
out=inp;
while(out.some(Array.isArray))
out=[].concat.apply([],out);
document.write(JSON.stringify(out))代码>一个相当简洁易读的算法:
function flatten2(input) {
var output = [];
var todo = [input];
var current;
var head;
while(todo.length) {
var current = todo.shift();
if(Array.isArray(current)) {
current = current.slice();
head = current.shift();
if(current.length) {
todo.unshift(current)
}
todo.unshift(head);
} else {
output.push(current);
}
}
return output;
}
function flatten(input) {
var output = [];
var todo = [input];
var current;
while(todo.length) {
var current = todo.shift();
if(Array.isArray(current)) {
todo.unshift.apply(todo, current)
} else {
output.push(current);
}
}
return output;
}
此版本的性能比我的好,但仍然比我的慢很多
这里有一个解决方案,它可以在适当的地方变平
function flatten(arr) {
var i = 0;
if (!Array.isArray(arr)) {
/* return non-array inputs immediately to avoid errors */
return arr;
}
while (i < arr.length) {
if (Array.isArray(arr[i])) {
arr.splice(i, 1, ...arr[i]);
} else {
i++;
}
}
return arr;
}
函数展平(arr){
var i=0;
如果(!Array.isArray(arr)){
/*立即返回非数组输入以避免错误*/
返回arr;
}
而(i
此解决方案在数组中迭代,一次将每个元素展平一级嵌套,直到无法再展平为止 函数展平(数组){
function flatten(array){
for(var i=0;i<array.length;i++)
if(Array.isArray(array[i]))
array.splice.apply(array,[i,1].concat(array[i--]));
return array;
}
对于(var i=0;i,这里有两种方法,递归和迭代,以及它们与Array.flat的比较。
也许它会帮助别人
const arraytoflant=[[1],[2[3]],null,[[{}]],未定义];
//获取数组并递归展平,默认深度为1(与array.flat()类似)
函数(arr,深度=1){
让myArray=[];
如果(深度===0){//如果已达到深度,请不要继续
myArray=arr;
}else如果(!Array.isArray(arr)){//如果不是数组,则将项添加到数组中
myArray.push(arr);
}else{//展平数组中的每个项,然后连接
arr.forEach(项目=>{
const someNewArray=递归(项,深度-1);
myArray=myArray.concat(someNewArray);
});
}
返回myArray;
}
//获取一个数组并使用循环将其展平,默认深度为1(与array.flat()类似)
函数(arr,深度=1){
设结果=arr;
//如果元素是数组
while(result.some(Array.isArray)和depth){
//通过浓缩空数组并使用apply将数组展平一级
结果=[].concat.apply([],结果);
深度--;//轨迹深度
}
返回结果;
}
console.log(arraytoflant.flat(2));//ES^
log(flattrecursive(arraytoflant,2));
console.log(flatteIterative(ArrayToFlatte,2));
以下是我的解决方案:
function flattenList(A) {
let result = []
for (let i=0; i < A.length; i++) {
if (typeof A[i] == "object"){
let item = reduceArray(A[i])
result.push(...item)
}else {
result.push(A[i])
}
}
return result
}
function reduceArray(arr){
while(arr.some(Array.isArray)) {
let item = arr.find(Array.isArray)
let index = arr.indexOf(item)
arr[index] = item[0]
}
return arr
}
功能列表(A){
让结果=[]
for(设i=0;i
出于好奇,你的递归解决方案是什么?可能与此作业重复?你为迭代解决方案做了哪些尝试?如果你已经有了递归解决方案,为什么还要追求迭代解决方案?请将递归解决方案添加到你的问题中,以便正确格式化。多行代码不可读在注释中。出于好奇,输入[1,{a:[2,3,4]}]
会发生什么?输出是否应该与输入相同或[1,{a:[2,3,4]}]
(或其他内容)?换句话说,展平过程是应该到达内部对象还是仅仅展平本身就是阵列的元素?与我预期的解决方案不太一样。:)尽管这很糟糕,但它实际上可能能够处理比递归或迭代解决方案更大的数组。一场枪战将是令人敬畏的:-)跳出框框思考的好方法。;)如果数组包含一些字符串,例如“go to supermarket[…]”
@nopole,那么它将不起作用,但对于带有数字的OPs情况,它确实起作用。另请参阅“但不推荐"。我将删除我的,反正它们是等效的。这可能更符合我认为面试官想要的。@JamesWilkins我已经尝试了更多的平台。你的代码始终是最快的,做得很好。:)谢谢。我在这里也做了类似的事情,以表明有时低级代码虽然复杂,但在spe中可以快得多特殊情况:可能是O(n)其中n是整个嵌套对象结构中的总项数。深度不相关。它可以很容易地成为具有相同项数的单个对象。开销不会像跳转到嵌套数组那样大。仅供参考,到目前为止,我已经为答案做了一个jsPerf:谢谢。我希望性能更清晰-那些slice
调用很慢。@Tomalak你让我想到了性能:-)这更好,但与James Wilkins的答案不符。我链接了你的JSPerf的一个新版本。这很好。比t更简单,可能更快,内存效率更高