假设我有一个像
这样的大型数组[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
对我来说就足够了。
答案 0 :(得分:5)
这应该有效:
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]] ]
答案 1 :(得分:5)
使用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
答案 2 :(得分: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);
答案 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中一样,这会删除不完整的块。