雙層循環(huán)
最原始的數(shù)組去重方式
var array = [1, 1, '1', '1']
function unique(array) {
var res = []
for (var i = 0, arrayLen = array.length; i < arrayLen; i++) {
for (var j = 0, resLen = res.length; j < resLen; j++) {
if (array[i] === res[j]) {
break
}
}
if (j === resLen) {
res.push(array[i])
}
}
return res
}
console.log(unique(array)) // [1, '1']
indexOf
var array = [1, 1, '1', '1']
function unique(array) {
var res = []
for (var i = 0, arrayLen = array.length; i < arrayLen; i++) {
var current = array[i]
if(res.indexOf(current) === -1) {
res.push(current)
}
}
return res
}
console.log(unique(array)) // [1, '1']
排序后去重
排序去去重是將數(shù)組進(jìn)行sort排序,相同的值就會被排在一起,然后我們就可以只判斷當(dāng)前元素與上一個元素是否相同,相同就說明重復(fù)
var array = [1, 2, 2, 1]
function unique(array) {
var res = []
var sortedArray = array.concat().sort()
var seen
for (var i = 0, arrayLen = array.length; i < arrayLen; i++) {
if (!i || seen !== sortedArray[i]) {
res.push(sortedArray[i])
}
seen = sortedArray[i]
}
return res
}
console.log(unique(array)) // [1, 2]
unique API
結(jié)合這兩種去重方式,我們嘗試寫一個工具函數(shù),我跟可根據(jù)一個參數(shù)isSorted判斷是否已經(jīng)排序過,如果為true,我們就判斷相鄰元素是否相同,如果為false,我們使用indexOf方式進(jìn)行判斷。考慮到數(shù)組中存在大小寫問題,例如‘a(chǎn)’和‘A’我們只保留一個,我們可以通過增加參數(shù)iteratee函數(shù)來讓處理方式再內(nèi)部數(shù)組循環(huán)中進(jìn)行自定義處理。
var arr = [1, 1, 'a', 'A', 2, 2]
function unique(array, isSorted, iteratee) {
var res = []
var seen = []
for (var i = 0, len = array.length; i < len; i++) {
var value = array[i]
var computed = iteratee ? iteratee(value, i, array) : value
if (isSorted) {
if (!i || seen !== computed) {
res.push(computed)
}
seen = computed
}
else if (iteratee) {
if (seen.indexOf(computed) === -1) {
seen.push(computed)
res.push(value)
}
}
else if (res.indexOf(value) === -1) {
res.push(value)
}
}
return res
}
console.log(unique(arr, true, function (item) {
return typeof item === 'string' ? item.toLowerCase() : item
}))
filter
indexOf方式
function unique(array) {
var res = array.filter(function(item, index, array) {
return array.indexOf(item) === index
})
return res
}
排序去重方式
function unique(array) {
var res = array.concat().sort().filter(function(item, index, array) {
return !index || (item !== array[index - 1])
})
return res
}
Object鍵值對
這種方式我們可以通過一個空的Object對象,把數(shù)組的值存為Object的key值,通過hanOwnProperty來判斷是否有值。
hanOwnProperty無法判別'1'和1的鍵值,我們可以使用typeof item + item的方式拼接來避免這個問題。
function unique(array) {
var obj = {}
var res = array.filter(function(item, index, array) {
return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
})
return res
}
ES6
ES6提供了新的數(shù)據(jù)結(jié)構(gòu)set和map,以set為例,它類似于數(shù)組,但是成員的值都是唯一的,沒有重復(fù)值。
function unique(array) {
return Array.from(new Set(array))
}
簡化一下
function unique(array) {
return [...new Set(array)]
}
再簡化一下
var unique6 = array => [...new Set(array)]
如果使用Map
function unique(array) {
var seen = new Map()
var res = array.filter((a) => {
return !seen.has(a) && seen.set(a, 1)
})
return res
}