JavaScript 中数组删除重复元素

Posted by cl9000 on June 21, 2020

生活只有在平淡无味的人看来才是空虚而平淡无味的。 ——<尼古拉·加夫里诺维奇·车尔尼雪夫斯基>

如果Array仅包含原始值,则可以仅使用 filterindexOf 方法对它进行重复数据删除。

1
2
3
4
5
var deduped = [ 1, 1, 'a', 'a' ].filter(function (el, i, arr) {
truereturn arr.indexOf(el) === i;
});

console.log(deduped); // [ 1, 'a' ]

ES2015

我们可以使用箭头功能以更紧凑的方式编写此代码。

1
2
3
var deduped = [ 1, 1, 'a', 'a' ].filter( (el, i, arr) => arr.indexOf(el) === i);

console.log(deduped); // [ 1, 'a' ]

但是通过引入 Setfrom方法,我们可以更简洁地达到相同的结果。

1
2
3
var deduped = Array.from( new Set([ 1, 1, 'a', 'a' ]) );

console.log(deduped); // [ 1, 'a' ]

对象
当元素是对象时,我们不能使用相同的方法,因为对象是通过引用存储的,而基元是通过值存储的。

1
2
3
4
5
1 === 1 // true

'a' === 'a' // true

{ a: 1 } === { a: 1 } // false

因此,我们需要更改方法并使用哈希表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function dedup(arr) {
truevar hashTable = {};

truereturn arr.filter(function (el) {
truetruevar key = JSON.stringify(el);
truetruevar match = Boolean(hashTable[key]);

truetruereturn (match ? false : hashTable[key] = true);
true});
}

var deduped = dedup([
true{ a: 1 },
true{ a: 1 },
true[ 1, 2 ],
true[ 1, 2 ]
]);

console.log(deduped); // [ {a: 1}, [1, 2] ]

由于 JavaScript 中的哈希表只是一个Object,因此键将始终为类型String。这意味着通常我们无法区分具有相同值(即1和)的 字符串和数字’1’。

1
2
3
4
5
6
var hashTable = {};

hashTable[1] = true;
hashTable['1'] = true;

console.log(hashTable); // { '1': true }

但是,因为我们正在使用 JSON.stringify,所以类型的键String将存储为转义的字符串值,从而在中提供了唯一的键hashTable

1
2
3
4
5
6
var hashTable = {};

hashTable[JSON.stringify(1)] = true;
hashTable[JSON.stringify('1')] = true;

console.log(hashTable); // { '1': true, '\'1\'': true }

这意味着相同值但类型不同的重复元素仍将使用相同的实现进行重复数据删除。

1
2
3
4
5
6
7
8
9
10
11
12
var deduped = dedup([
true{ a: 1 },
true{ a: 1 },
true[ 1, 2 ],
true[ 1, 2 ],
true1,
true1,
true'1',
true'1'
]);

console.log(deduped); // [ {a: 1}, [1, 2], 1, '1' ]

参考

关注【公众号】,了解更多。



支付宝打赏 微信打赏

赞赏一下 坚持原创技术分享,您的支持将鼓励我继续创作!