数组中数据全部为基本数据类型
1、Set方法配合展开运算符实现
原数组不会被改变
const data = [1,3,4,"4",5,"4","7",undefined,7,7, NaN, undefined, NaN, null, null]
function unique(arr) {
if (!arr || arr.length === 0) return []
return [...new Set(arr)]
}
console.log(unique(data)) // [1, 3, 4, "4", 5, "7", undefined, 7, NaN, null]
思路:利用Set方法不能含有相同值的特性,返回时利用展开运算符(...)返回一个新的数组,因此原数组不会被改变。
2、Set方法配合Array.from方法实现
原数组不会被改变
const data = [1,3,4,"4",5,"4","7",undefined,7,7, NaN, undefined, NaN, null, null]
function unique(arr) {
if (!arr || arr.length === 0) return []
return Array.from(new Set(arr))
}
console.log(unique(data)) // [1, 3, 4, "4", 5, "7", undefined, 7, NaN, null]
思路:利用Array.from
方法,该方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。因此原数组不会被改变。
3、for循环配合数组indexOf方法实现
原数组不会被改变
const data = [1,3,4,"4",5,"4","7",undefined,7,7, NaN, undefined, NaN, null, null]
function unique(arr) {
if (!arr || arr.length === 0) return []
let ary = []
for(let i = 0, length = arr.length; i < length; i++) {
if (ary.indexOf(arr[i]) === -1) {
ary.push(arr[i])
}
}
return ary
}
console.log(unique(data)) // [1, 3, 4, "4", 5, "7", undefined, 7, NaN, NaN, null]
思路:利用一层for循环遍历,在for循环的代码块中再使用数组的indexOf
方法,来判断新声明的数组中是否存在当前项的索引,
从而达到去重的效果,由于是新声明的数组来存放去重后的数据,因此原数组不会被改变。
4、for循环配合数组includes方法实现
原数组不会被改变
const data = [1,3,4,"4",5,"4","7",undefined,7,7, NaN, undefined, NaN, null, null]
function unique(arr) {
if (!arr || arr.length === 0) return []
let ary = []
for(let i = 0, length = arr.length; i < length; i++) {
if (!ary.includes(arr[i])) {
ary.push(arr[i])
}
}
return ary
}
console.log(unique(data)) // [1, 3, 4, "4", 5, "7", undefined, 7, NaN, null]
思路:这种实现方式与上面的indexOf方法实现的一样,原数组也不会被改变。
5、利用Map方法实现
原数组不会被改变
const data = [1,3,4,"4",5,"4","7",undefined,7,7, NaN, undefined, NaN, null, null]
function unique(arr) {
if (!arr || arr.length === 0) return []
let map = new Map()
let ary = []
for(let i = 0, len = arr.length; i < len; i++) {
if (map.has(arr[i])) {
map.set(arr[i], true)
} else {
map.set(arr[i], false)
ary.push(arr[i])
}
}
return ary
}
console.log(unique(data)) // [1, 3, 4, "4", 5, "7", undefined, 7, NaN, null]
思路:利用一层for循环遍历,在for循环的代码块中再使用Map的has
和set
方法,来判断新声明的数组中是否存在当前项,存在的话将其value设置为true,反之设置为false并使用额外声明的数组变量保存起来,由于是新声明的数组来存放去重后的数据,因此原数组不会被改变。
6、利用Map方法配合数组的filter方法实现
原数组不会被改变
const data = [1,3,4,"4",5,"4","7",undefined,7,7, NaN, undefined, NaN, null, null]
function unique(arr) {
if (!arr || arr.length === 0) return []
let map = new Map()
return arr.filter(item => !map.has(item) && map.set(item, 1))
}
console.log(unique(data)) // [1, 3, 4, "4", 5, "7", undefined, 7, NaN, null]
思路:利用数组的filter
方法的特性,该方法会返回一个新的数组,因此原数组不会被改变。
7、利用reduce方法实现
原数组不会被改变
const data = [1,3,4,"4",5,"4","7",undefined,7,7, NaN, undefined, NaN, null, null]
function unique(arr) {
if (!arr || arr.length === 0) return []
let ary = arr.reduce((accumulator, current) => {
return accumulator.includes(current) ? accumulator : accumulator.concat(current)
}, [])
return ary
}
console.log(unique(data)) // [1, 3, 4, "4", 5, "7", undefined, 7, NaN, null]
思路:利用数组的reduce
方法实现,上面这种实现方式原数组不会被改变。其实reduce方法很强大,可以做很多事情,例如:数组去重、数组降维(拍平)、数组求和等等,这里就不赘述了。
8、利用对象键值对
原数组不会改变
const data = [1,3,4,"4",5,"4","7",undefined,7,7, NaN, undefined, NaN, null, null]
function unique(arr) {
if (!arr || arr.length === 0) return []
let map = {}
let ary = []
for(let i = 0, len = arr.length; i < len; i++) {
if (map[arr[i]]) continue
ary.push(arr[i])
map[arr[i]] = true
}
return ary
}
console.log(unique(data)) // [1, 3, 4, 5, "7", undefined, NaN, null]
思路:利用for循环,将遍历的子项存放到map对象中,不存在就放到新数组中,这种方式原数组也不会被改变。缺点就是如果string和number类型的值时相等的,那么也会被过滤掉,这种方式限制比较大。
9、双层for循环方法实现(一)
原数组会被改变
const data = [1,3,4,"4",5,"4","7",undefined,7,7, NaN, undefined, NaN, null, null]
function unique(arr) {
if (!arr || arr.length === 0) return []
for(let i = 0, len = arr.length; i < len; i++) {
for(let j = i + 1, len = arr.length; j < len; j++) {
if (arr[i] === arr[j]) {
arr.splice(j, 1)
j--
len--
}
}
}
return arr
}
console.log(unique(data)) // [1, 3, 4, "4", 5, "7", undefined, 7, NaN, NaN, null]
思路:使用双重for循环,外层循环控制次数,内层循环将j
变量赋值为i + 1
, 在循环体中判断外层循环的索引项与内层循环的索引项是否相等,如果相等
利用splice
方法将当前项删除,同时将j
和arr数组的长度同时减一,如此往复从而实现去重,由于是直接操作传进来的参数,并将该参数返回出去,
因此原数组会被改变。
10、双层for循环方法实现(二)
原数组不会改变
const data = [1,3,4,"4",5,"4","7",undefined,7,7, NaN, undefined, NaN, null, null]
function unique(arr) {
let ary = []
if (!arr || arr.length === 0) return []
for(var i = 0, len = arr.length; i < len; i++) {
for(var j = 0, aryLen = ary.length; j < aryLen; j++) {
if (arr[i] === ary[j]) break
}
if (j === aryLen) {
ary.push(arr[i])
}
}
return ary
}
console.log(unique(data)) // [1, 3, 4, "4", 5, "7", undefined, 7, NaN, NaN, null]
思路:两层for循环,外层循环遍历的是入参数组,内层循环遍历的是新声明的ary
数组,在内层循环体中判断,两个数组中对应的索引值是否相等,相等跳出循环,外层循环体中判断变量j
和ary
数组的长度是否相等, 由于是新声明的数组来存放去重后的数据,因此原数组不会被改变。
11、使用sort方法排序后去重
原数组不会改变
const data = [1,3,4,"4",5,"4","7",undefined,7,7, NaN, undefined, NaN, null, null]
function unique (arr) {
if (!arr || arr.length === 0) return []
let ary = arr.sort()
let flag;
let result = []
for(let i = 0, len = ary.length; i < len; i++) {
// 判断是否为第一个元素或者相邻的元素不相同
if (!i || flag !== ary[i]) {
result.push(ary[i])
}
flag = ary[i]
}
return result
}
console.log(unique(data)) // [1, 3, 4, "4", 5, "7", 7, NaN, NaN, null, undefined]
思路:先利用排序方法排序后,再判断相邻两个元素是否相同的思路,一层for循环控制遍历次数,循环体中判断是否为第一个元素或者相邻的元素不相同,条件为真时将数据放入新声明的数组中。由于是新声明的数组来存放去重后的数据,因此原数组不会被改变。
总结
这些方法都是针对一维数组且数组不为对象数组的方法,下面为了方便对比,直接将几种方法进行了对比,这些实现方式最后的结果会有差别,但这不是最重要的,重要的是我们要知道什么场景使用什么方式去解决才好。
方法序号 | 打印结果 | 说明 | 1 | [1, 3, 4, "4", 5, "7", undefined, 7, NaN, null] | 对NaN可以去重 | 2 | [1, 3, 4, "4", 5, "7", undefined, 7, NaN, null] | 对NaN可以去重 | 3 | [1, 3, 4, "4", 5, "7", undefined, 7, NaN, NaN, null] | 对NaN不能去重 | 4 | [1, 3, 4, "4", 5, "7", undefined, 7, NaN, null] | 对NaN可以去重 | 5 | [1, 3, 4, "4", 5, "7", undefined, 7, NaN, null] | 对NaN可以去重 | 6 | [1, 3, 4, "4", 5, "7", undefined, 7, NaN, null] | 对NaN可以去重 | 7 | [1, 3, 4, "4", 5, "7", undefined, 7, NaN, null] | 对NaN可以去重 | 8 | [1, 3, 4, 5, "7", undefined, NaN, null] | 对NaN可以去重,值相同的string和number根据先后顺序会被去重 | 9 | [1, 3, 4, "4", 5, "7", undefined, 7, NaN, NaN, null] | 对NaN不能去重 | 10 | [1, 3, 4, "4", 5, "7", undefined, 7, NaN, NaN, null] | 对NaN不能去重 | 11 | [1, 3, 4, "4", 5, "7", 7, NaN, NaN, null, undefined] | 对NaN不能去重 |
---|
参考文章
github.com/mqyqingfeng…
www.cnblogs.com/echolun/p/1…
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!