[译] 如何在 ES6 中数组去重?

270 阅读3分钟

原文:medium.com/dailyjs/how…

作者:Samantha Ming


以下是从数组中过滤重复项并只返回唯一值的三种方法。我最喜欢的是使用 `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.fromSet转换为数组:

Array.from() 方法从一个类似数组或可迭代对象中创建一个新的,浅拷贝的数组实例。

const array = ['🐑', 1, 2, '🐑', '🐑', 3];

Array.from(new Set(array));

// ['🐑', 1, 2, 3];

2. Filter

为了理解这个方法,我们来看看这两个方法的作用:indexOffilter

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]

参考