数组去重
原始变量
如果一个数组只包含原始变量,我们可以使用filter
和indexOf
方法将其去重:
var deduped = [ 1, 1, 'a', 'a' ].filter(function (el, i, arr) {
return arr.indexOf(el) === i;
});
console.log(deduped); // [ 1, 'a' ]
ES2015
我们可以使用箭头函数使写法更简明:
var deduped = [ 1, 1, 'a', 'a' ].filter( (el, i, arr) => arr.indexOf(el) === i);
console.log(deduped); // [ 1, 'a' ]
但是根据Sets和from
方法的介绍,我们可以更简明的实现。
var deduped = Array.from( new Set([ 1, 1, 'a', 'a' ]) );
console.log(deduped); // [ 1, 'a' ]
Objects
当元素为对象(Object)时,我们就不能用这种办法了, 因为对象存储的是引用而原始变量存储的是值。
1 === 1 // true
'a' === 'a' // true
{ a: 1 } === { a: 1 } // false
因此我们需要改变一下我们的实现方法,使用哈希表。
function dedup(arr) {
var hashTable = {};
return arr.filter(function (el) {
var key = JSON.stringify(el);
var match = Boolean(hashTable[key]);
return (match ? false : hashTable[key] = true);
});
}
var deduped = dedup([
{ a: 1 },
{ a: 1 },
[ 1, 2 ],
[ 1, 2 ]
]);
console.log(deduped); // [ {a: 1}, [1, 2] ]
因为哈希表在Javascript里是一个简单的Object
,它的key
永远是String
类型。这意味着我们不能区分字符串和数字表示的相同的值,如1
和'1'
。
var hashTable = {};
hashTable[1] = true;
hashTable['1'] = true;
console.log(hashTable); // { '1': true }
然而,因为我们使用的JSON.stringify
,String
类型的key
将会被存储为一个字符串值,这样hashTable
的key
就唯一了。
var hashTable = {};
hashTable[JSON.stringify(1)] = true;
hashTable[JSON.stringify('1')] = true;
console.log(hashTable); // { '1': true, '\'1\'': true }
这意味着相同的值,但不同类型的元素,将以原来的格式保留。
var deduped = dedup([
{ a: 1 },
{ a: 1 },
[ 1, 2 ],
[ 1, 2 ],
1,
1,
'1',
'1'
]);
console.log(deduped); // [ {a: 1}, [1, 2], 1, '1' ]
阅读材料
函数
ES2015
Stack overflow
MEET THE NEW JSTIPS BOOK
You no longer need 10+ years of experience to get your dream job.
Use the 100 answers in this short book to boost your confidence and skills to ace the interviews at your favorite companies like Twitter, Google and Netflix.
GET THE BOOK NOW
MEET THE NEW JSTIPS BOOK
The book to ace the JavaScript Interview.
A short book with 100 answers designed to boost your knowledge and help you ace the technical interview within a few days.
GET THE BOOK NOW