展平N维JavaScript数组

时间:2014-02-25 19:05:21

标签: javascript jquery arrays

我想将N维数组拼成单个数组。该数组只有数字,但每个元素本身不一定是数组。样本数据: (md =多维)fiddle

 var mdArray = [1,2,[3, 4], [[[5, 6, 7]]]];


 Array.prototype.flattenAll = function () {
         var self = this,
         //finds elements that are not arrays
             numbers = $.grep(self, function (n, i) {
                 return !$.isArray(n);
             }),
         //gets md arrays
             nestedArrays = $.grep(self, function (n, i) {
                 return $.isArray(n);
             }),
             returnArray = [];
         nestedArrays = $.map(nestedArrays, function (a, ix) {
             return a.flatten();
         });
         return returnArray.concat(numbers).concat(nestedArrays);
     };
     Array.prototype.flatten = function () {
             return this.reduce(function (a, b) {
                 return a.concat(b);
             });
     }

flatten函数适用于简单的数组数组,但不适用于秩为>的数组。这似乎是一个简单的递归修复,但我没有看到它。在没有更多阵列变平的情况下,我在这里错过了什么才能让flatten运行?

7 个答案:

答案 0 :(得分:2)

一个非常简单的循环可以解决这个问题:

Array.prototype.flattenAll = function () {
    var flattened = this.slice();
    for (var i=0; i<flattened.length; )
        if ($.isArray(flattened[i]))
            flattened.splice.apply(flattened, [i, 1].concat(flattened[i]));
        else
            i++;
    return flattened;
}

答案 1 :(得分:2)

您可以使用Array.prototype.reduce

在一个语句中执行此操作
Array.prototype.flatten = function (){
    return this.reduce(function(c,x){
        return Array.isArray(x) ? c.concat(x.flatten()) : c.concat(x);
    }, []);
}

顺便说一句,如果你要修改核心对象原型(比如Array.prototype),你应该至少使用Object.defineProperty,这样你的函数就不可枚举了:

Object.defineProperty(Array.prototype, 'flatten', {
    value: function (){
        return this.reduce(function(c,x){
            return Array.isArray(x) ? c.concat(x.flatten()) : c.concat(x);
        }, []);
    },
    enumerable: false
});

如果您想了解为什么不使用Object.defineProperty这是一个坏主意,请尝试以下操作:

Array.prototype.foo = function(){};
console.log([1,2,3]);

您将在Chrome中看到的是:

[1, 2, 3, foo: function]

可能不是任何人想要看到的......使用Object.defineProperty并将enumerable设置为false可以防止这种情况发生。

其他浏览器的控制台日志不太友好。但是如果你想要一个可以在任何浏览器中使用的铁板示例,请执行以下操作:

Array.prototype.foo = function(){};
for(var x in [1,2,3]) console.log(x):

答案 2 :(得分:2)

你可以用漂亮的递归来做到这一点:

function flatten(array, i) {
  i = ~~i;

  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 :(得分:1)

var mdArray = [1,2,[3, 4], [[[5, 6, 7]]]];
function flatten(mdArray){
    var data = [];
    $.each(mdArray,function(index,item){
        if(typeof(item) != 'object'){
            data.push(item);
        }else{
            data = data.concat(flatten(item));
        }
    });
    return data;
}
var result = flatten(mdArray);
console.log(result);

答案 4 :(得分:0)

function flattenArrayOfArrays(a, r){
    if(!r){ r = []}
    for(var i=0; i<a.length; i++){
        if(a[i].constructor == Array){
            flattenArrayOfArrays(a[i], r);
        }else{
            r.push(a[i]);
        }
    }
    return r;
}

答案 5 :(得分:0)

您可以使用lodashflatten运营商;

var mdArray = [1,2,[3, 4], [[[5, 6, 7]]]];

console.log(_.flatten(mdArray)); // Outputs [1, 2, 3, 4, 5, 6, 7] 

答案 6 :(得分:0)

这是针对此问题的Vanilla JavaScript解决方案

&#13;
&#13;
var _items = {'keyOne': 'valueOne', 'keyTwo': 'valueTwo', 'keyThree': ['valueTree', {'keyFour': ['valueFour', 'valueFive']}]};

// another example
// _items = ['valueOne', 'valueTwo', {'keyThree': ['valueTree', {'keyFour': ['valueFour', 'valueFive']}]}];

// another example
/*_items = {"data": [{
    "rating": "0",
    "title": "The Killing Kind",
    "author": "John Connolly",
    "type": "Book",
    "asin": "0340771224",
    "tags": "",
    "review": "i still haven't had time to read this one..."
}, {
    "rating": "0",
    "title": "The Third Secret",
    "author": "Steve Berry",
    "type": "Book",
    "asin": "0340899263",
    "tags": "",
    "review": "need to find time to read this book"
}]};*/

function flatten() {
    var results = [],
        arrayFlatten;

    arrayFlatten = function arrayFlattenClosure(items) {
        var key;
        
        for (key in items) {
            if ('object' === typeof items[key]) {
                arrayFlatten(items[key]);
            } else {
                results.push(items[key]);
            }
        }
    };

    arrayFlatten(_items);
    
    return results;
}

console.log(flatten());
&#13;
&#13;
&#13;