以下是从数组中过滤重复项并只返回唯一值的三种方法。我最喜欢的是使用 `Set`,因为它是最短的和最简单的😁
const array = ['🐑', 1, 2, '🐑', '🐑', 3];
// 1: 'Set'
[...new Set(array)];
// 2: 'Filter'
array.filter((item, index) => array.indexOf(item) === index);
// 3: 'Reduce'
array.reduce((unique, item) =>
unique.includes(item) ? unique : [...unique, item], []);
// RESULT:
// ['🐑', 1, 2, 3];
1. Set
让我先解释一下 Set是什么:
Set是 ES6 中引入的新数据对象。因为Set只允许你存储唯一值。当你传入数组时,它将删除任何重复值。
好了,让我们回到代码并分解正在发生的事。有两件事:
-
首先,我们通过传递一个数组来创建一个新的
Set。由于Set只允许唯一值,所以所有重复项将被删除。 -
现在重复项已删除,我们要使用扩展运算符
...将其转换回数组。
const array = ['🐑', 1, 2, '🐑', '🐑', 3];
// Step 1
const uniqueSet = new Set(array);
// Set { '🐑', 1, 2, 3 }
// Step 2
const backToArray = [...uniqueSet];
// ['🐑', 1, 2, 3];
使用 Array.from 将 Set 转换为数组
或者,你也可以使用Array.from将Set转换为数组:
Array.from() 方法从一个类似数组或可迭代对象中创建一个新的,浅拷贝的数组实例。
const array = ['🐑', 1, 2, '🐑', '🐑', 3];
Array.from(new Set(array));
// ['🐑', 1, 2, 3];
2. Filter
为了理解这个方法,我们来看看这两个方法的作用:indexOf和filter。
indexOf
indexOf方法返回它从数组中找到的给定元素的第一个索引。
const array = ['🐑', 1, 2, '🐑', '🐑', 3];
array.indexOf('🐑'); // 0
array.indexOf(1); // 1
array.indexOf(2); // 2
array.indexOf(3); // 5
filter
filter方法创建一个新的数组,其包含符合给定筛选条件的元素。换句话说,如果元素符合并返回true,它将包含在已过滤数组中。如果不符合或返回false,就不会包含。
const array = ['🐑', 1, 2, '🐑', '🐑', 3];
array.filter((item, index) => {
console.log(
// a. Item
item,
// b. Index
index,
// c. indexOf
array.indexOf(item),
// d. Condition
array.indexOf(item) === index,
);
return array.indexOf(item) === index
});
// ['🐑', 1, 2, 3];
下面是上面显示的console.log的输出。索引与 indexOf不相等的地方是重复值。在这些情况下,条件将为false并不会包含在过滤后的数组中。
| Item | Index | indexOf | Condition |
|---|---|---|---|
| 🐑 | 0 | 0 | true |
| 1 | 1 | 1 | true |
| 2 | 2 | 2 | true |
| 🐑 | 3 | 0 | false |
| 🐑 | 4 | 0 | false |
| 3 | 5 | 5 | true |
检索重复值
我们还可以使用filter方法从数组中检索重复值。 我们可以通过简单地调整条件来做到这一点:
const array = ['🐑', 1, 2, '🐑', '🐑', 3];
array.filter((item, index) => array.indexOf(item) !== index);
// ['🐑', '🐑']
同样,如果我们执行上面的代码并查看输出:
| Item | Index | indexOf | Condition |
|---|---|---|---|
| 🐑 | 0 | 0 | false |
| 1 | 1 | 1 | false |
| 2 | 2 | 2 | false |
| 🐑 | 3 | 0 | true |
| 🐑 | 4 | 0 | true |
| 3 | 5 | 5 | false |
3. Reduce
reduce方法用于减少数组的元素,并根据传递的某个reducer函数将它们组合成一个最终数组。
在本例中,我们的reducer函数检查最终数组是否包含该项。如果没有,则将该项推入最终数组。否则,跳过该元素并按原样返回起最终数组(基本上跳过该元素)。
reducer函数总是有点难以理解,所以让我们看看每种情况下的输出:
const array = ['🐑', 1, 2, '🐑', '🐑', 3];
array.reduce((unique, item) => {
console.log(
// a. Item
item,
// b. 最终数组(Accumulator:累计器)
unique,
// c. Condition (只有为 false 时才会推入最终数组)
unique.includes(item),
// d. Reducer function Result
unique.includes(item) ? unique : [...unique, item],
);
return unique.includes(item) ? unique : [...unique, item]
}, []); // 👈 Accumulator 的初始值为空数组
// ['🐑', 1, 2, 3];
这是console.log的输出:
| Item | 累加器(Reducer 函数之前) | 推入累计器? | 累加器(Reducer 函数之后) |
|---|---|---|---|
| 🐑 | [] | Yes | ['🐑'] |
| 1 | ['🐑'] | Yes | ['🐑', 1] |
| 2 | ['🐑', 1] | Yes | ['🐑', 1, 2] |
| 🐑 | ['🐑', 1, 2] | No | ['🐑', 1, 2] |
| 🐑 | ['🐑', 1, 2] | No | ['🐑', 1, 2] |
| 3 | ['🐑', 1, 2] | Yes | ['🐑', 1, 2, 3] |