根据条件将JavaScript数组分成两个或多个数组
在处理数据时,数组的分割通常很有用。从概念上讲,将数组分割成两个数组与过滤非常相似,但不是从数组中删除元素,而是根据提供的函数的真值将它们分组。对于多个分区,概念上非常相似,但实现上稍微复杂一些。
将数组分割成两个
两个分区是最简单的情况,需要很少的工作。我们只需要使用Array.prototype.reduce()
创建一个包含两个数组的数组。然后,我们调用给定的函数,并使用Array.prototype.push()
将fn
返回true
的元素添加到第一个数组中,将fn
返回false
的元素添加到第二个数组中。
const partition = (arr, fn) =>
arr.reduce(
(acc, val, i, arr) => {
acc[fn(val, i, arr) ? 0 : 1].push(val);
return acc;
},
[[], []]
);
const users = [
{ user: 'barney', age: 36, active: false },
{ user: 'fred', age: 40, active: true },
];
partition(users, o => o.active);
// [
// [{ user: 'fred', age: 40, active: true }],
// [{ user: 'barney', age: 36, active: false }]
// ]
将数组分割成多个数组
根据提供的函数的返回值,将数组分割成任意数量的数组会更具挑战性一些。我们仍然可以利用Array.prototype.reduce()
,但是不再使用包含两个数组的数组作为累加器,而是使用Map
对象。这将允许我们将元素分组成所需数量的数组。
它还允许我们通过使用Map.prototype.has()
来轻松检查分区是否已存在。如果存在,我们可以将元素简单地添加到现有分区中。如果不存在,我们可以创建一个包含该元素的数组的新分区。
最后,我们使用Map.prototype.values()
获取Map
对象的值的迭代器,并使用扩展运算符(...
)将其转换为数组。
const partitionBy = (arr, fn) => [
...arr
.reduce((acc, val, i, arr) => {
const current = fn(val, i, arr);
if (acc.has(current)) acc.get(current).push(val);
else acc.set(current, [val]);
return acc;
}, new Map())
.values(),
];
const numbers = [1, 1, 3, 3, 4, 5, 5, 5];
partitionBy(numbers, n => n % 3);
// [[1, 1, 4], [3, 3], [5, 5, 5]]
partitionBy(numbers, n => n);
// [[1, 1], [3, 3], [4], [5, 5, 5]]