本章要将的东西分前后两个:两数全等 与数组去重
但其实就是一个东西,判断两复杂 对象是否全等
引导 在这之前可能大部分人认为两数相等,== 就行了呀,不行我就 === ,这总可以了吧
虽说 === 是要满足数据类型一致的前提下,满足数据相等。可以满足基本需求
但只对基本类型可行,若是遇到引用类型,即Object 对象或Array 数组时呢
1 2 3 4 5 6 7 8 9 10 11 console.log ([] === []) let obj1 = { a: 1 , b: 2 } let obj2 = { a: 1 , b: 2 } console.log (obj1 == obj2)
抱歉,管你一不一样,都返回false
即这种 === 对引用类型是无效的
到这可能会有人想把引用类型转化为字符串 再去判断不就可以了吗
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 let arr1 = [1 , 2 , 3 ]let arr2 = [1 , 2 , 3 ]console .log(arr1.toString() == arr2.toString())let obj1 = { a: 1 , b: 2 } let obj2 = { a: 1 , b: 2 } console .log(JSON .stringify(obj1) == JSON .stringify(obj2))
但是 ,如果数组或对象的值的只是顺序不同 呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 let arr1 = [1 , 2 , 3 ] let arr2 = [3 , 1 , 2 ] let obj1 = { a : 1 , b : 2 } let obj2 = { b : 1 , a : 2 }
到这可能会有人想把数组或对象先排序 之后再转化为字符串,再来判断相等
1 2 3 4 5 6 7 8 9 10 11 12 13 console.log(arr1.sort().toString() == arr2.sort().toString()) function objSort (obj) { let sdic = Object.keys(obj).sort() let new Obj = {} for (ki in sdic){ new Obj [sdic[ki]] = obj[sdic[ki]] } return new Obj }
通过排序之后,两数组或对象的顺序是一样的,转化为字符串,再判断
但是 ,如果该数组或对象的值的类型不一致呢?
1 2 3 let arr1 = [1 , '3 ', '2 '] let arr2 = [1 , 2 , 3 ]
是不是觉得上面的方法不可用了呢
再但是 ,如果该数组或对象的值也是一个引用类型呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 let arr = [ [1 , 2 , 2 ], [2 , 1 , 1 ], [2 , 1 , 3 ] ] let obj ={ a : { b : 1 , a : 1 }, b : { a : 1 , b : '1' , } }
你猜猜看 [1, 2, 2] 和 [2, 1, 1] 谁前谁后?
a: { b: 1, a: 1} 和 b: { a: 1, b: ‘1’} 谁前谁后?
有兴趣你可以自己排序输出看一看,验证自己的猜想
在进一步看,如果数组或对象的值复杂多变,对象嵌数组,数组再嵌对象….
两数相等 所以我这要讲的是这样的两数相等:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 foo1 = { a: 1 , d: [{ b: '3' , a: 1 }, [2 , 1 ]], c: false, f: { a: '1' , e: [2 , 1 ], c: { d: 1 , f: '1' } }, e: ['2' , 1 ]} foo2 = { a: '1' , c: false, d: [[1 , 2 ], { a: 1 , b: '3' }], f: { e: ['2' , 1 ], a: '1' , c: { d: '1' , f: 1 } }, e: [1 , '2' ]}
思路分四层:
存在其中有一个数不是对象,走 ===
一数组,另一非数组,直接false
两数均为数组,走数组逻辑(较麻烦)
两都为非数组对象,走对象逻辑
完整判断两数相等函数 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 function isEqual (obj1, obj2 ) { if (!(obj1 instanceof Object ) || !(obj2 instanceof Object )) { return obj1 === obj2 } if (obj1 instanceof Array != obj2 instanceof Array ) { return false } else if (obj1 instanceof Array && obj2 instanceof Array ) { if (obj1.length != obj2.length) { return false } else { let arr = new Array (obj2.length).join(0 ).split(' ' ) for (let item1 of obj1){ let i; for (i = 0 ; i < obj2.length ; i++){ if (arr[i] != 1 &&isEqual(item1,obj2[i])) { arr[i] = 1 break ; } } if (i>=obj2.length) { return false } } return true } } else { if (Object .keys(obj1).length != Object .keys(obj2).length) { return false } for (let attr in obj1){ if (!obj2.hasOwnProperty(attr)) { return false } if (!isEqual(obj1[attr], obj2[attr])) { return false } } return true } }
通用方法,类型复杂多变,要考虑所有情况,
数组去重 对于普通的的数组,去重方法有很多种,直接遍历,利用indexOf索引,利用对象的属性等等。
以及ES6的Set
1 2 3 4 function dedupe (array ) { return Array .from(new Set (array)) } dedupe([1 ,1 ,2 ,3 ])
1 2 3 let arr = [1 ,2 ,3 ,3 ] let new Arr = [...new Set (arr)] console.log(new Arr )
但通过上面的分析,也应当知道,此处要讲的也不是简单的数组,数组的每一项也是复杂多变的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 let arr2 = [ 2 , { b : 2 , a : 1 , c: [3 ] },{ a : 1 , b : 2 , c: [3 ] }, '2' , ['1' , 2 , 1 ], [2 , '1' , 1 ] ]
这样的数组,用上面的去重方法,都行不通
但我们已经有了一个判断两数相等的函数了不是吗
故数组去重函数 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function removeDuplication (array) { let new Arr = [] for (let item of array) { let i for (i=0 ; i<new Arr .length;i++) { if (isEqual(item, new Arr [i])) { break ; } } if (i>=new Arr .length) { new Arr .push(item) } } return new Arr }
利用isEqual去检索是否已经包含该数值。
总结 本次分享了两个函数,两数相等isEqual 函数,数组去重removeDuplication 函数
基本通用
如若有误,可diss我, 欢迎指正
如若你有更好的方法,Share ~