JS数组去重2017
来源:互联网 发布:js把毫秒数转换成日期 编辑:程序博客网 时间:2024/06/07 09:47
现在要求去重下面这个数组
[1, 2, 3, 3, 3, '0', '1', '2', '测试', '重复', '重复', NaN, NaN, false, false];
方法一:ES6 Set()
let arr = [1, 2, 3, 3, 3, '0', '1', '2', '测试', '重复', '重复', NaN, NaN, false, false];arr = [...new Set(arr)]; //去重后: [ 1, 2, 3, '0', '1', '2', '测试', '重复', NaN, false ]
Set 是ES6新加的集合,集合中的值不会重复。 ...操作符 会将可遍历对象,转换为数组.
方法二:利用对象
let arr = [1, 2, 3, 3, 3, '0', '1', '2', '测试', '重复', '重复', NaN, NaN, false, false];let obj ={};let temp=[];for( let i = 0; i < arr.length; i++ ) {let type= Object.prototype.toString.call(arr[i]);//不加类型 分不清 1 '1' if( !obj[ arr[i] +type] ) { temp.push( arr[i] ); obj[ arr[i]+ type ] =true;//这里给true 利于代码阅读和判断。 如果给 0,'' ,false ,undefined 都会在if那里判断为 false 不利于代码阅读 }}console.log(temp)//去重后: [ 1, 2, 3, '0', '1', '2', '测试', '重复', NaN, false ]
方法三:sort排序后 在去重
let arr = [1, 2, 3, 3, 3, '0', '1', '2', '测试', '重复', '重复', NaN, NaN, false, false];arr = arr.sort();let temp =[];while(arr.length > 0) { if( Object.is(arr[0], arr[1]) ) {//Object.is() 用于比较2个值, 比===更靠谱 例如 Object.is(NaN,NaN) 会判断true arr.shift(); }else{ temp.push( arr.shift() );}}//此方法会清空原数组, 你可以复制个数组,在去进行操作console.log(temp)//去重后: [ '0', 1, '1', '2', 2, 3, NaN, false, '测试', '重复' ]
方法四:for in
let arr = [1, 2, 3, 3, 3, '0', '1', '2', '测试', '重复', '重复', NaN, NaN, false, false];let temp =[];for(let i = 0; i < arr.length; i++) { if( !temp.includes( arr[i]) ) {//includes 检测数组是否有某个值 内部调用Object.is() 利用判断NaN temp.push(arr[i]); }}console.log(temp);//去重后: [ 1, 2, 3, '0', '1', '2', '测试', '重复', NaN, false ]
以上方法 在最新版本谷歌浏览器全部正常运行; 建议大家都用谷歌浏览器
基础版-只包含一些可以直接比较的数值
测试数组
[1,1,'','','e','e',true,'true',true,false,false,'false',undefined,'undefined',undefined,null,'null',null]
- [ES5]万能的
for
方法
function uniqueUseFor(array) { var temp = []; //一个临时数组 //遍历当前数组 for (var i = 0, j = array.length; i < j; i++) { //很直白,新数组内判断是否有这个值,没有的情况下,就推入该新数组 temp.indexOf(array[i]) === -1 ? temp.push(array[i]) : ''; } return temp;}// result: [1, "", "e", true, "true", false, "false", undefined, "undefined", "null", null]
- [ES5]内置的
forEach
方法
function uniqueUseForEach(array) { // 传入值必须存在,且长度小于等于1的时候直接返回数组 if (array && array.length <= 1) { return array; } else { var temp = []; //一个临时数组 //遍历当前数组 array.forEach(function (value, index) { temp.indexOf(value) == -1 ? temp.push(value) : ''; }) return temp; }}// result: [1, "", "e", true, "true", false, "false", undefined, "undefined", "null", null]
- [ES6]内置的
for-of
方法
function uniqueUseForOf(array) { const temp = []; //一个临时数组 // 传入值必须存在,且长度小于等于1的时候直接返回数组 if (array && array.length <= 1) { return array; } else { //遍历当前数组 for (let x of array) { temp.indexOf(x) === -1 ? temp.push(x) : ''; } } return temp;}// result: [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']
知识点
NaN有两中通用判定方法和数组中一种判定方法:
- 一个是绝对不全等于(
===
)自身 - 一个是
ES6
的isNaN()
- 数组原型链上的
Array.prototype.includes()
- 一个是绝对不全等于(
[ES5]: 不等特性,需要借助占位符
function uniqueUseNotAllEqual(array) { var temp = [], //一个临时数组 mark = true; // 标识位 //遍历当前数组 for (var i = 0, j = array.length; i < j; i++) { // 标识位的作用就是用来判断是否存在NaN,第一次找到保留到新数组中 // 然后标识位置改为false是为了再次找到的时候不推入数组 if (array[i] !== array[i]) { // 这里的不等特性,也可以用isNaN判断[ES6] mark && temp.indexOf(array[i]) == -1 ? temp.push(array[i]) : ''; mark = false; } else temp.indexOf(array[i]) == -1 ? temp.push(array[i]) : ''; } return temp;}// 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 temp = []; //一个临时数组 //遍历当前数组 for (let x of array) { // includes() 方法用来判断当前数组是否包含某指定的值,如果是,则返回 true,否则返回 false。 temp.includes(x) ? '': temp.push(x) ; } return temp; }}// result: [1, "true", true, 5, "F", false, undefined, null, NaN, 0, "a", "NaN"]
- [ES6]
Array.from
或拓展运算符[...
]结合Set
大法
知识点
Set
的值具有唯一性,内部会自动===
比较,是可迭代对象(iterable),有点特殊的是NaN
这货虽然有不全等的特性,在Set
里面认为是相同的,所以只能有一个Array.from
和...
可以把类似数组【nodelist or arguments】这类可迭代的对象中转为一个标准的数组
// Array.from + Set的方法Array.from(new Set([1,1,'true',true,true,5,'F',false, undefined, null,null,undefined, NaN, 0, 1, 'a', 'a', NaN,'NaN']))// resule: [1, "true", true, 5, "F", false, undefined, null, NaN, 0, "a", "NaN"]// ... + Set的方法[...new Set([1,1,'true',true,true,5,'F',false, undefined, null,null,undefined, NaN, 0, 1, 'a', 'a', NaN,'NaN'])]//result: [1, "true", true, 5, "F", false, undefined, null, NaN, 0, "a", "NaN"]
高阶版- 包含{}
,NaN
,undefined
,null
测试数组
[1,1,'true',true,true,5,'F',false, undefined, null,null,undefined, NaN,{},{},'{}', 0, 1, 'a', 'a', NaN]
知识点
{}
的比较真心不好做,有残缺性的比较可以这样写JSON.stringify({}) == '{}'
一个比较完美的方案是借助
for in
结合原型链的toString
来判断[ES5]
for-in
+call
+for
方案
function uniqueUseForIn(array) { var temp = []; 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 && temp.indexOf(array[i]) == -1 ? temp.push(array[i]) : ''; emptyObjectMark = false; } else if (array[i] !== array[i]) { NaNObjectMark && temp.indexOf(array[i]) == -1 ? temp.push(array[i]) : ''; NaNObjectMark = false; } else temp.indexOf(array[i]) == -1 ? temp.push(array[i]) : ''; } return temp; }}// result:[1, "true", true, 5, "F", false, undefined, null, NaN, Object, "{}", 0, "a"]
拓展版:多维数组扁平化再去重;
回应:
留言板的小伙伴说去重深度不够。。2017/5/12
测试数组
[1, 1, [['true', true, true, [5, 'F'], false], undefined], null, null, [undefined, NaN, {}], {}, '{}', 0,1, 'a','a', NaN]
知识点
- 数组扁平化用了递归实现
- 代码也考虑了默认参数,防止不传递参数的时候报错
- [ES5]
for-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) { for (var m = 0, n = arr.length; m < n; m++) { if (Array.isArray(arr[m])) { var _tempSpliceArr = _array.splice(m, 1)[0]; _array = _array.concat(_tempSpliceArr); 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 temp = []; var emptyObjectMark = true; // 标识位 var NaNObjectMark = true; // 标识位 console.log(_array.length) //遍历当前数组 for (var a = 0, b = _array.length; a < b; a++) { // 标识位的作用就是用来判断是否存在NaN和空对象,第一次找到保留到新数组中 // 然后标识位置改为false是为了再次找到的时候不推入数组 console.log(_array[a]); if (isEmptyObject(_array[a])) { emptyObjectMark && temp.indexOf(_array[a]) == -1 ? temp.push(_array[a]) : ''; emptyObjectMark = false; } else if (_array[a] !== _array[a]) { NaNObjectMark && temp.indexOf(_array[a]) == -1 ? temp.push(_array[a]) : ''; NaNObjectMark = false; } else { temp.indexOf(_array[a]) === -1 ? temp.push(_array[a]) : ''; } } console.log(temp); return temp; }}// result:[1, null, Object, "{}", 0, "a", NaN, undefined, "true", true, false, 5, "F"]// 用ES6来写的话,应该代码量可以稍微再精简些
- JS数组去重2017
- JS 数组去重
- js数组去重
- js 数组去重
- js 数组去重
- js数组去重
- js 数组去重
- js数组去重
- JS 数组去重
- //js数组去重
- js-数组去重
- js数组去重
- js 数组去重
- js数组去重
- JS 数组去重
- JS 数组去重
- js数组去重
- JS 数组去重
- Android studio无线调试
- 脉冲云为何要用docker
- 2.1 通过极限获得切线斜率
- nrf51822-主从通信分析2
- 复杂链表的复制
- JS数组去重2017
- org.dom4j.DocumentException: null Nested exception: null
- linux给文件授权
- windows 使用sc命令将程序注册成服务 实现后台运行开机自启
- 抓包工具Fidder详解(主要来抓取Android中app的请求)
- Spark的Master,Worker调试
- 为什么要设置Java环境变量(详解)
- oracle sql日期比较
- Hibernate框架-多对一和一对多关联