[TOC] >[success] # 比较两个数组 ~~~ 1.有时候我们想比较a,b两个数组中元素是否相同,因为数组是引用类型,因此不是按值进行比较,举个例子 说明 const a = [1, 2, 3]; const b = [1, 2, 3]; a === b; // false ~~~ [原文javascript-array-comparison](https://www.30secondsofcode.org/blog/s/javascript-array-comparison) >[info] ## toString 和 join ~~~ 1.再简单的两个数组比较的时候可以常使用'toString 和 join',这种方式不推荐 2.toString 和 join 使用产生情况是相同的下面代码以join为例 ~~~ >[danger] ##### 简单数组类型使用 ~~~ 1.下面案例中满足比较的两个数组,他们的特点数组中每一项是常量,这一类型的数组通过转换成字符串 在进行比较 ~~~ ~~~ const {log} = console const equals = (a,b) => a.join() === b.join() const simpleLs = [1,2,3,'w'] const simpleLs1 = [1,2,3,'w'] log(equals(simpleLs,simpleLs1)) // true ~~~ >[danger] ##### 这种比较的弊端 ~~~ 1.使用'toString 和 join' 这种形式问题会很多 举几个例子'数组中的值非常量'、'数组中的值有null或undefined' 这些都会让我们得到的结果出现问题 2.下面案例打印的值都应该为false ,但是操作结果为true ~~~ * 得到的结果和预期不符 ~~~ const {log} = console const equals = (a,b) => a.join() === b.join() // 产生错误 const ls = [1,2,3,[5,6,[7]]] const ls1 = [1,2,3,5,6,7] log(equals(ls,ls1)) // true const lsObj = [{name:'20'}] const lsObj1 = [{name:'190'}] log(equals(lsObj,lsObj1)) // true const lsempty = [null] const lsempty1 = [undefined] log(equals(lsempty,lsempty1))// true const type = [new String('a')] const type1 = ['a'] log(equals(type,type1))// true ~~~ >[info] ## JSON.stringify ~~~ 1.JSON.stringify(),它允许我们序列化每个数组,然后比较两个序列化的字符串,虽然这种写法能解决 使用'toString 和 join' 这种写法的大部分问题,但是也是有弊端 ~~~ >[danger] ##### 使用 ~~~ 1.下面案例可以解决'toString 和 join' ,对于嵌套和对象这种项产生的问题 ~~~ ~~~ const {log} = console const equals = (a,b) => JSON.stringify(a) === JSON.stringify(b) // 产生错误 const ls = [1,2,3,[5,6,[7]]] const ls1 = [1,2,3,5,6,7] log(equals(ls,ls1)) // false const lsObj = [{name:'20'}] const lsObj1 = [{name:'190'}] log(equals(lsObj,lsObj1)) // false ~~~ >[danger] ##### 弊端 ~~~ 1.JSON.stringify(),虽然可以帮助解决大部分场景的两个数组值的比较但是也有相对问题依旧是null 和 undefined,和通过对象创建常量和常量比较情况 ~~~ ~~~ const {log} = console const equals = (a,b) => JSON.stringify(a) === JSON.stringify(b) // 产生错误 const lsempty = [null] const lsempty1 = [undefined] log(equals(lsempty,lsempty1))// true const str = 'a'; const strObj = new String('a'); str === strObj; // false equals([str], [strObj]); // true, should be false ~~~ >[info] ## 通过every 和 length ~~~ 1.可以利用length 先判数组长度是否一致作为优先判断两个数组是否相同条件 2.在使用every 判断A数组中每一项 是否和B数组中对应项相等,来决定是否两个数组一致 ~~~ >[danger] ##### 代码实现 ~~~ 1.但是产生问题没有考虑嵌套数组或对象,需要对它们进行递归检查 ~~~ ~~~ const equals = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]); const a = [1, 2, 3]; const b = [1, 2, 3]; const str = 'a'; const strObj = new String('a'); equals(a, b); // true equals([str], [strObj]); // false equals([null], [undefined]); // false ~~~ >[danger] ##### 解决递归问题 [代码来源equals](https://www.30secondsofcode.org/js/s/equals) ~~~ const equals = (a, b) => { if (a === b) return true; if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b; if (a.prototype !== b.prototype) return false; let keys = Object.keys(a); if (keys.length !== Object.keys(b).length) return false; return keys.every(k => equals(a[k], b[k])); }; 例子 equals( { a: [2, { e: 3 }], b: [4], c: 'foo' }, { a: [2, { e: 3 }], b: [4], c: 'foo' } ); // true equals([1, 2, 3], { 0: 1, 1: 2, 2: 3 }); // true ~~~ >[info] ## 只关心内容的比较 ~~~ 1.有时候我们不关心顺序是否一致更多关系两个数组中值是否相同,例如 [1,3,2] 和 [3,2,1] 判断为true 每个数组中元素的顺序并不重要,我们只关心两个数组中存在的相同值 ~~~ [have-same-contents](https://www.30secondsofcode.org/js/s/have-same-contents) ~~~ const haveSameContents = (a, b) => { for (const v of new Set([...a, ...b])) if (a.filter(e => e === v).length !== b.filter(e => e === v).length) return false; return true; }; haveSameContents([1, 2, 4], [2, 4, 1]); // true ~~~