双层循环
最原始的数组去重方式
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']
排序后去重
排序去去重是将数组进行sort排序,相同的值就会被排在一起,然后我们就可以只判断当前元素与上一个元素是否相同,相同就说明重复
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
结合这两种去重方式,我们尝试写一个工具函数,我跟可根据一个参数isSorted判断是否已经排序过,如果为true,我们就判断相邻元素是否相同,如果为false,我们使用indexOf方式进行判断。考虑到数组中存在大小写问题,例如‘a’和‘A’我们只保留一个,我们可以通过增加参数iteratee函数来让处理方式再内部数组循环中进行自定义处理。
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对象,把数组的值存为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提供了新的数据结构set和map,以set为例,它类似于数组,但是成员的值都是唯一的,没有重复值。
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
}