Javascript修复我的flatten(数组)函数

时间:2014-06-17 21:04:00

标签: javascript recursion flatten

我无法弄清楚为什么我的代码没有按照指示展平嵌套数组。我非常感谢这里的一些帮助。我使用递归来获取嵌套数组的实际值。我试图调试我的代码,似乎每次递归都会替换我的结果数组。

//Helper methods

function toType(obj){
    return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

function each(collection, callback){
    if (Array.isArray(collection)){
        for (var i = 0; i < collection.length; i++){
            callback(collection[i], i, collection)
        }
    } else {
        for (var i in collection){
            callback(collection[i], i, collection)
        }
    }
}

//Flatten function

function flatten(array, isShallow=false, callback){
    var results = [];
    each(array, function(item){
        if (!!isShallow && toType(item) === 'array'){
            each (item, function(value){
                results.push(value);
            })
        } else if (toType(item) !== 'array'){
            results.push(item);
        } else {
            return flatten(item)
        }
    })
    return results;
}

flatten([1, [2], [3, [[4]]]]);

// ---> [1]

5 个答案:

答案 0 :(得分:2)

您的问题似乎与此行有关:

return flatten(item)

返回此处是一个问题,因为循环将结束,结果中的当前条目将被忽略,以及其余项目。该行应更改为添加

的结果
flatten(item) 
通过推送

到结果数组。

我建议使用库来做这类事情。 http://underscorejs.org/#flatten是一个很棒的人!

答案 1 :(得分:1)

请参阅下面的重构代码。

主要的变化是,我们不是创建results的新副本,而是将其传递给后续调用以作为参考。

请参阅添加的评论

//Helper methods

function toType(obj){
    return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

function each(collection, callback){
    if (Array.isArray(collection)){
        for (var i = 0; i < collection.length; i++){
            callback(collection[i], i, collection)
        }
    } else if(typeof collection === 'object'){ 
        //type number was failing here
        for (var i in collection){
            callback(collection[i], i, collection)
        }
    }
    else {
        //default for primitive types
        callback(collection, 0, collection);
    }
}
//Flatten function

//Removed isShallow, how do we know if its shallow or not?
//Added results as arg, so we only manipulate the reference to results
//And to not create multiple scopes of var results;
function flatten(array, results, callback){
    results = results || [];
    each(array, function(item){

        //removed 3rd if clause not needed. 
        //Only need to know if item is an object or array
        if (toType(item) === 'array' || toType(item) === 'object'){
            each (item, function(value){
                flatten(value,results);
            })
        } else {
            results.push(item);
        }
    })

    return results;
}


var array1 = [1,[2,[3,4]]];
var array2 = [5,[6,[7,[8, {a:9,b:[10,11,12]}]]]];
var obj = {a:array1, b:array2};


console.log(flatten(array1)); // [ 1, 2, 3, 4 ]
console.log(flatten(array2)); // [ 5, 6, 7, 8, 9, 10, 11, 12 ]
console.log(flatten(obj)); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]

答案 2 :(得分:0)

你可以这样做:

function flatten(array, i) {
  i = i || 0;

  if(i >= array.length)
    return array;

  if(Array.isArray(array[i])) {
    return flatten(array.slice(0,i)
      .concat(array[i], array.slice(i+1)), i);
  }

  return flatten(array, i+1);
}

示例:

var weirdArray = [[],1,2,3,[4,5,6,[7,8,9,[10,11,[12,[[[[[13],[[[[14]]]]]]]]]]]]]
flatten(weirdArray);
//returns ==> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

答案 3 :(得分:0)

在javascript中展平数组的最好方法是使用Array的拼接功能。请遵循以下代码。它也适用于嵌套。

 function flattenArray(arr){

  for(var i=0;i<arr.length;i++){

    if(arr[i] instanceof Array){

      Array.prototype.splice.apply(arr,[i,1].concat(arr[i]))
    }

  }

  return arr;
}

答案 4 :(得分:-1)

使用underscore.js的展平函数(http://underscorejs.org/#flatten)。 Underscore.js是一个第三方库,具有80多个奇怪的功能,使您作为javascript程序员的生活更轻松。不要重新发明轮子。

var _ = require('underscore');
_.flatten([1, [2], [3, [[4]]]]);
=> [1, 2, 3, 4];