我有一个相同的需求,但是需要按每个值的函数分组(而不是值本身)。例如,
[1, 3, 5, 2, 4, 6, 7, 8, 9, 10, 42]
成为
[[1, 3, 5], [2, 4, 6], [7], [8], [9], [10, 42]]
给定分组函数。
function (a) { return a % 2; }
一种方法是扩展 @dfsq 的方法,但使用按字典顺序作用域的
fn_prev
来避免重新计算先前的
fn(val)
。
var fn_prev = null;
myArray.reduce((acc, val) => {
let fn_curr = fn(val);
if (!acc.length || fn_curr !== fn_prev) {
acc.push([val]);
} else {
acc[acc.length - 1].push(val);
}
fn_prev = fn_curr;
return acc;
}, []);
我觉得避免使用.reduce
更为直接:
let fn_prev = null;
let acc = [];
for (let val of myArray) {
let fn_curr = fn(val);
if (!acc.length || fn_curr !== fn_prev) {
acc.push([val]);
} else {
acc[acc.length - 1].push(val);
}
fn_prev = fn_curr;
}
console.log(acc);
这可以像以下这样添加到数组原型中:
Object.defineProperty(Array.prototype, 'groupByAdjacent', {
value: function(fn) {
let fn_prev = null;
let acc = [];
for (let val of [].concat(this)) {
let fn_curr = fn(val);
if (!acc.length || fn_curr !== fn_prev) {
acc.push([val]);
} else {
acc[acc.length - 1].push(val);
}
fn_prev = fn_curr;
}
return acc;
}
});
并且像这样使用:
let x = [1, 3, 5, 2, 4, 6, 7, 8, 9, 10, 42];
let grouped_x = x.groupByAdjacent(a => a
console.log(grouped_x);
prev
是到目前为止已经构建的数组部分,curr
是我们正在查看的元素。我们要么将其添加到分组数组中的最后一个数组中,要么开始一个新的数组。如果prev.length
为0,则其值为false,这可以防止我们在第一次迭代中访问索引-1。 - Gamma032