Appearance
1.双for循环(拿当前项和后面的每一项比较,重点:数组塌陷和性能优化)
js
function unique (array) {
for (let i = 0; i < array.length - 1; i++) {
// 每一次拿出来的和后面每一项比较
for (let j = i + 1; j < array.length; j++) {
if (array[i] === array[j]) {
array.splice(j, 1)
// splice存在问题:1.数组塌陷 2.性能(如果删除的这一项后面还有1000万项,这1000万项的索引都要向前移一位)
// 原数组[1, 2, 1, 1, 2]
// i = 1; j = 2时 删除第二项,数组塌陷,后面索引都往前移一位
// [1, 2, 1, 1, 2] => [1, 2, 1, 2]
// j++ => j = 3, 直接跳过了修改后的原始数组第二项的1
// 解决办法 先让j--,之后再j++,相当于没加没减,下一轮还是和当前索引项的元素比较,
// 但是性能上没有优化
j--
}
}
}
return array
}js
function unique (array) {
for (let i = 0; i < array.length - 1; i++) {
for (let j = i + 1; j < array.length; j++) {
if (array[i] === array[j]) {
// 性能优化
// 当前项值是重复的,但是不删除,让当前项的值等于最后一项的值
// 再把最后一项删除
// [1, 1, 2, 1, 3] => [1, 3, 2, 1, 3] => [1, 3, 2 ,1]
// 下一轮比较时:还要和当前的索引比,因为当前索引项值变为最后一项了
array[j] = array[array.length - 1]
array.length--
i--
}
}
}
return array
}2.单for循环 + 存储容器
js
function unique2 (array) {
if (!Array.isArray(array)) throw new Error('argument must be an array')
const resArr = []
for (let i = 0; i < array.length; i++) {
if (resArr.indexOf(array[i]) === -1) resArr.push(array[i])
}
return resArr
}3.对象键值对方式,分别取出每一项的值作为对象的属性名存储,每次存储前看对象中是否存在这个属性,以此判断是否重复 1.一个循环,性能更好 2.如果数组出现引用类型则存在问题,因为对象属性名不能是对象 3.数字x和字符串'x'也会被认为是重复的
js
function unique (array) {
const obj = {}
for (let i = 0; i < array.length; i++) {
const item = array[i]
if (obj.hasOwnProperty(item)) {
const lastIdx = array.length - 1
array[i] = array[lastIdx]
array.length--
i--
continue
}
obj[item] = item
}
return array
}4.对象键值对 + 存储容器
js
function unique3 (array) {
if (!Array.isArray(array)) throw new Error('argument must be an array')
const resArr = []
const o1 = {}
for (let i = 0; i < array.length; i++) {
if (!o1.hasOwnProperty(array[i])) {
o1.array[i] = true
resArr.push(array[i])
}
}
return resArr
}ES6 Set 能够去除引用数据类型的重复
js
function unique (array) {
return [...new Set(array)]
// return Array.from(new Set(array))
}通过正则去重
js
function unique(array) {
array.sort((a, b) => a - b)
let str = array.join('@') + '@' // '1@1@1@2@2@3@3@4@5@'
let reg = /(\d+@)\1*/g
let result = []
str.replace(reg, (n, m) => {
m = Number(m.slice(0, m.length - 1))
result.push(m)
})
return result
}