今天主要就是了解了一下关于数组去重的方法,下面就说说怎么去重,以及去重的方法。
数组去重,这是一个老梗了…今天我又拿出来说了… 我们在考虑全面一点的情况下,数组去重的实现,比如针对NaN,undefined,{}; 这其中涉及的知识点挺多,不信跟着走一波; 这里不考虑浏览器兼容性这些破问题,因为涉及ES5&6
下面就从四个阶段来说
基础版
测试数组
[1,1,’’,’’,‘e’,‘e’,true,‘true’,true,false,false,‘false’,undefined,‘undefined’,undefined,null,‘null’,null]
- ES5万能的
for
方法
/**
* 使用ES5的for方法来实现
* 实现方法:
* 1、定义一个空的数组,用来保存去重后的数据
* 2、遍历所有的数据,根据下标,判断新数组内是否有这个值,没有的情况下,就推入该新数组。
* indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
* 注释:indexOf() 方法对大小写敏感!
注释:如果要检索的字符串值没有出现,则该方法返回 -1。
* 1、使用indexOf()方法来做三目运算,并判断,
如果新的数组内的值等于-1,就说明新数组中没有这个值,然后就是把这个值添加到新的数组内;
如果不等于-1,就证明当前的值,在新数组内存在过,把当前的值等于空,即可(即删除)。
*/
function uniqueUseFor(arr) {
var temp = []; //一个临时的数组
// 遍历当前的数组
for (var i = 0; i < arr.length; i++) {
temp.indexOf(arr[i] == -1) ? temp.push(arr[i]) : ""
}
return temp;
}
console.log(uniqueUseFor(arr));
// 结果: [1, 1, "", "", "e", "e", true, "true", true, false, false, "false", undefined, "undefined", undefined, null, "null", null]
- ES5内置的
forEach
方法
/**
* 使用ES5的forEach的方法
* 实现方法:
* 1、定义一个空的数组,用来保存去重后的数据
* 2、遍历所有的数据,拿到每个值,判断新数组内是否有这个值,没有的情况下,就推入该新数组。
* indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
* 注释:indexOf() 方法对大小写敏感!
注释:如果要检索的字符串值没有出现,则该方法返回 -1。
* 1、使用indexOf()方法来做三目运算,并判断,
如果新的数组内的值等于-1,就说明新数组中没有这个值,然后就是把这个值添加到新的数组内;
如果不等于-1,就证明当前的值,在新数组内存在过,把当前的值等于空,即可(即删除)。
*/
function uniqueUseFor(arr) {
var temp = [];
arr.forEach(item => {
temp.indexOf(item) == -1 ? temp.push(item) : ""
})
return temp;
}
console.log(uniqueUseFor(arr))
//结果: [1, "", "e", true, "true", false, "false", undefined, "undefined", null, "null"]
- [ES6]内置的
for-of
方法
/**
* 使用ES6的for of方法
* 实现方法:
* 1、定义一个空的数组,用来保存去重后的数据
* 2、遍历所有的数据,拿到每个值,判断新数组内是否有这个值,没有的情况下,就推入该新数组。
* indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
* 注释:indexOf() 方法对大小写敏感!
注释:如果要检索的字符串值没有出现,则该方法返回 -1。
* 1、使用indexOf()方法来做三目运算,并判断,
如果新的数组内的值等于-1,就说明新数组中没有这个值,然后就是把这个值添加到新的数组内;
如果不等于-1,就证明当前的值,在新数组内存在过,把当前的值等于空,即可(即删除)。
*
*/
function uniqueUseFor(arr) {
var temp = [];
for (let x of arr) {
temp.indexOf(x) == -1 ? temp.push(x) : ""
}
return temp;
}
console.log(uniqueUseFor(arr));
//结果: [1, "", "e", true, "true", false, "false", undefined, "undefined", null, "null"]
进阶版
包含NaN
,undefined
,null
测试数组
[1,1,‘true’,true,true,5,‘F’,false, undefined, null,null,undefined, NaN, 0, 1, ‘a’, ‘a’, NaN,‘NaN’]
function uniqueUseNotAllEqual(array) {
var tmp = [] //一个临时数组
mark = true; //标识位
// 遍历当前数组
for (var i = 0, j = array.length; i < j; i++) {
// 标识符的作用就是用来判断是否存在NaN,第一次找不到保留到新数组中
// 然后标识位置改为false是为了再次找到的时候不推入数组
if (array[i] !== array[i]) {
// 这里的不等特性,也可以用isNaN判断[ES6]
mark && tmp.indexOf(array[i]) === -1 ? tmp.push(array[i]) : "";
mark = false
} else {
tmp.indexOf(array[i]) === -1 ? tmp.push(array[i]) : "";
}
}
console.log(tmp)
return tmp;
}
uniqueUseNotAllEqual(array)
//结果: result: [1, "true", true, 5, "F", false, undefined, null, NaN, 0, "a", "NaN"]
- ES6内置Array.prototype.includes()大法
function uniqueCompareUseIncludes(array) {
// 传入值必须存在,且长度小于等于1的时候直接返回数组
if (array && array.length <= 1) {
return array
} else {
let tmp = []; //一个临时数组
// 遍历当前数组
for (let x of array) {
// includes()方法用来判断当前数组是否有指定包含的值,如果有返回true没有返回false
tmp.includes(x) ? "" : tmp.push(x)
}
console.log(tmp)
return tmp
}
}
uniqueCompareUseIncludes(array)
//结果: result: [1, "true", true, 5, "F", false, undefined, null, NaN, 0, "a", "NaN"]
[es6] Array.from或扩展运算符[…]结合set大法
/*
* 知识点
* 1.Set的值具有唯一性,内部会自动===比较,
* 是可迭代对象(iterable),有点特殊的是NaN这货虽然有不全等的特性,
* 在Set里面认为是相同的,所以只能有一个
* 2.Array.from和…可以把类似数组【nodelist or arguments】
* 这类可迭代的对象中转为一个标准的数组
*/
// Array.from+Set的方法
let arr = Array.from(new Set([1, 1, 'true', true, true, 5, 'F', false, undefined, null, null, undefined, NaN, 0, 1, 'a', 'a', NaN, 'NaN']))
console.log(arr)
// ... 扩展运算符 +Set的方法
let arrTow = [...new Set([1,1,'true',true,true,5,'F',false, undefined, null,null,undefined, NaN, 0, 1, 'a', 'a', NaN,'NaN'])]
console.log(arr)
高阶版
包含{},NaN,undefined,null
测试数组
let array = [1, 1, ‘true’, true, true, 5, ‘F’, false, undefined, null, null, undefined, NaN, {}, {}, ‘{}’, 0, 1, ‘a’, ‘a’, NaN]
- ES5 fro-in + call +for 方案
function uniqueUseForIn(array) {
var tmp = [];
var emptyObjectMark = true; //标识位
var NaNObjectMark = true; //标识位
// 判断空对象
function isEmptyObject(object) {
if (Object.prototype.toString.call(object) === "[object Object]") {
for (var i in object) {
// 存在属性和方法,则不是空对象
return false
}
return true;
} else {
return false
}
}
// 传入值必须存在,且长度等于小于1的时候返回数组
if (array && array.length <= 1) {
return array
} else {
// 遍历当前数组
for (var i = 0, j = array.length; i < j; i++) {
//标识位的作用就是用来判断是否存在NaN和空对象,第一次找到保留到新数组中
//然后标识位置改为false是为了再次找到的时候不推入数组
if (isEmptyObject(array[i])) {
emptyObjectMark && tmp.indexOf(array[i]) == -1 ? tmp.push(array[i]) : "";
emptyObjectMark = false
} else if (array[i] !== array[i]) {
NaNObjectMark && tmp.indexOf(array[i]) == -1 ? tmp.push(array[i]) : "";
NaNObjectMark = false
} else {
tmp.indexOf(array[i]) == -1 ? tmp.push(array[i]) : "";
}
}
console.log(tmp)
return tmp;
}
}
uniqueUseForIn(array)
//结果: result:[1, "true", true, 5, "F", false, undefined, null, NaN, Object, "{}", 0, "a"]
拓展版
多维数组扁平化再去重;
测试数组
let array = [1, 1, [[‘true’, true, true, [5, ‘F’], false], undefined], null, null, [undefined, NaN, {}], {}, ‘{}’, 0, 1, ‘a’, ‘a’, NaN]
/*
* 知识点
* 数组扁平化用了递归实现
* 代码也考虑了默认参数,防止不传递参数的时候报错
* ES5for-in + call + for +递归扁平化方案
*/
function uniqueArrayWithFlattern(array) {
var _array = array || []
function isEmptyObject(object) {
if (Object.prototype.toString.call(object) === "[object Object]") {
for (var i in object) {
return false
}
return true
} else {
return false
}
}
// 遍历查询判断,扁平化数组
function forArrayFlattern(arr) {
// console.log("fenqian",arr)
for (var m = 0, n = arr.length; m < n; m++) {
if (Array.isArray(arr[m])) {
// console.log("分割2",_array.splice(m,1))
// console.log("分割1",_array)
var _tmpSpliceArr = _array.splice(m, 1)[0];
// console.log("分割完",_tmpSpliceArr)
_array = _array.concat(_tmpSpliceArr)
// console.log("==========================",_array)
return forArrayFlattern(_array)
}
}
return uniqueArr(_array)
}
// 传入值必须存在,且长度小于等于1的时候直接返回数组
if (_array && _array.length <= 1) {
return _array
} else {
if (Array.isArray(_array)) {
return forArrayFlattern(_array)
} else {
return _array
}
}
// 数组去重
function uniqueArr(_array) {
var tmp = [];
var emptyObjectMark = true;
var NaNObjectMark = true;
// 遍历当前数组
for (var a = 0, b = _array.length; a < b; a++) {
if (isEmptyObject(array[a])) {
emptyObjectMark && tmp.indexOf(_array[a]) == -1 ? tmp.push(_array[a]) : ""
emptyObjectMark = false
} else if (_array[a] !== _array[a]) {
NamedNodeMap && tmp.indexOf(_array[a]) == -1 ? tmp.push(_array[a]) : ""
NamedNodeMap = false
} else {
tmp.indexOf(_array[a]) == -1 ? tmp.push(_array[a]) : ""
}
}
console.log(tmp)
return tmp
}
}
uniqueArrayWithFlattern(array)
// result:[1, null, Object, "{}", 0, "a", NaN, undefined, "true", true, false, 5, "F"]
详细了解移步JS数组去重!!!一篇不怎么靠谱的"深度"水文