如何从单个数组创建数组集合?

问题描述 投票:0回答:5

假设我有一个大数组,例如

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

并且想将其分成 n 元组数组,例如

[[1,2], [3,4], [5,6], [7,8], [9,10], [11,12], [13,14] /*, ... */ ] // (for n=2)

有一些简单的方法可以实现这一目标吗?特殊情况

n = 2
对我来说就足够了。

javascript arrays underscore.js
5个回答
6
投票

这应该有效:

for (var i=0; i<arr.length; i+=2) {
  result.push([arr[i], arr[i+1]]);
}

想出这个,它应该适用于任意数量的“口袋”或任何你想称呼它们的东西。它会检查

undefined
,因此它适用于奇数个项目:

Array.prototype.pockets = function(n) {

  var result = [],
      pocket = [],
      i, j;

  for (i=0; i<this.length; i+=n) {
    pocket.length = 0;
    for (j=1; j<n; j++) if (this[i+j] != null) pocket.push(this[i+j]);
    result.push([this[i]].concat(pocket));
  }

  if (arguments.length > 1) {
    return result.pockets.apply(result, [].slice.call(arguments,1));
  }

  return result;
};

// Usage:
var arr = [1,2,3,4,5,6,7,8,9,10,11];

arr.pockets(2); //=> [[1,2],[3,4],[5,6],[7,8],[9,10],[11]]
arr.pockets(3); //=> [[1,2,3],[4,5,6],[7,8,9],[10,11]]

// Recursive:
arr.pockets(1,3); //=> [ [[1],[2],[3]], [[4],[5],[6]], [[7],[8],[9]], [[10],[11]] ]

6
投票

使用

Array.slice
可以更简单地完成此操作:

function grouper(lst, size) {
    var result = [], i=0, n=lst.length;
    while(i < n) {
        result.push(lst.slice(i, i+size));
        i += size;
    }
    return result
}

效率也更高:http://jsperf.com/grouper


3
投票

对于下划线变体,您可以使用

_.groupBy()
来实现此目的,按项目的索引进行分组:

var doubles = _.groupBy(singles, function (num, i) {
    return Math.floor(i / 2);
});

不过,由于

_.groupBy()
返回
Object
,因此获得
Array
需要一些额外的工作:

_.mixin({
    segment: function (coll, per) {
        var result = [];
        _.chain(coll)
            .groupBy(function (item, i) { return Math.floor(i / per)})
            .each(function (group, key) { result[key] = group; })
        return result;
    }
});

var singles = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18];

var doubles = _.segment(singles, 2);
var triples = _.segment(singles, 3);

1
投票

在 python 中,这可以通过

zip(*[iter(xs)]*n)
来完成。只是为了好玩,这里有一个 JS 实现:

让我们从穷人的生成器开始(这就是 ES6 普及之前我们所拥有的一切):

StopIteration = {"name": "StopIteration"}

function iter(xs) {
    if('next' in xs)
        return xs;
    var i = 0;
    return {
        next: function() {
            if(i >= xs.length)
                throw StopIteration;
            return xs[i++];
        }
    }
}

next = function(it) { return it.next() }

zip()
是微不足道的:

zip = function() {
    var args = [].map.call(arguments, iter), chunks = [];
    while(1) {
        try {
            chunks.push(args.map(next));
        } catch(StopIteration) {
            return chunks;
        }
    }
}

现在,要创建链对,只需将相同的 iter 传递两次即可进行 zip:

xs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

it = iter(xs)
a = zip(it, it)

console.log(a)
// [[1,2],[3,4],[5,6],[7,8],[9,10],[11,12]]

对于 N 对,需要额外的实用程序:

repeat = function(x, n) {
    for(var a = []; n; n--)
        a.push(x);
    return a;
}

a = zip.apply(this, repeat(iter(xs), 5))

console.log(a) 
// [[1,2,3,4,5],[6,7,8,9,10]]

请注意,就像在 Python 中一样,这会删除不完整的块。


0
投票

您可以使用归约和模数 (%) 来做到这一点:

const grouper = (array, n) => array.reduce((a, b, i) => {
        i % n == 0 ?
            a.push([b])
            :
            a[a.length - 1].push(b);
        return a;
    }, []);

let result = grouper([1,2,3,4,5,6,7,8],2);    

console.log(result);
//[[1,2],[3,4],[5,6],[7,8]]

您可以在这里阅读有关 JavaScript reduce 的内容。

© www.soinside.com 2019 - 2024. All rights reserved.