Instruction
看题就要看一会,大致意思就是:比较数组a是否和数组b拥有相同的元素。这个‘相同’是指不论顺序,数组a中数字的平方一一对应数组b中的数字。
一开始我的解决方案是这样的:
1 function comp(array1, array2){ 2 var arr1 = array1 || ''; 3 var arr2 = array2 || ''; 4 if(arr1.length === 0 || arr2.length === 0) return false; 5 if(arr1.length != arr2.length) return false; 6 arr1.map(t=>t*t).forEach(function(s){ 7 if(arr2.indexOf(s)){ 8 arr2.splice(arr2.indexOf(s),1) 9 }else{ 10 return false; 11 } 12 }); 13 return true; 14 }
但是报错了。因为:
1,arr2.indexOf(s)这里没处理好,当找到的下标为0时,会返回false。
2,在forEach中,return false是跳出数组的forEach循环,接着运行comp接下来的方法,而不是跳出comp函数。
所以,可以将以上方法改进一下,变成:
function comp(array1, array2){ var flag = true; if(array1 == null || array2 == null) return false; array1.map(t=>t*t).forEach(function(s){ if(array2.indexOf(s) >= 0){ array2.splice(array2.indexOf(s),1) }else{ flag = false; } }); return flag; }
这样测试全部通过。可是总觉得太迂回了点,效率不那么高,却找不到好的思路,只好去学习网友的思路,于是我找到了:JS比较两个数组是否相等,是否拥有相同元素
这里面给我提供了一个新的思路:与其去一一对比,删除array2中的元素,何不重新排序后,简化成字符串作对比?这样就不存在数组增减的问题了
于是我修改了我的代码:
function comp(array1, array2){ if(array1 == null || array2 == null) return false; return flag = array1.map(t=>t*t).sort().toString() === array2.sort().toString() ? true : false; }
答案区里的最受好评的方法思路也差不多,只是在实践上更好:
function comp(array1, array2) { if(array1 == null || array2 == null) return false; array1.sort((a, b) => a - b); array2.sort((a, b) => a - b); return array1.map(v => v * v).every((v, i) => v == array2[i]); }
因为sort()排序不一定是稳定的,这里说明一下sort的语法。
arr.sort(compareFunction):compareFunction是可选的,用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的诸个字符的Unicode位点进行排序。
例如,数字比大小时,9出现在80之前,但这里比较时数字会先被转换为字符串,所以‘80’比‘9’要靠前。
如果指明compareFunction,那么数组将会按照调用该函数的返回值来排序。即a和b是两个将要被比较的元素:
- 如果compareFunction(a,b)小于0,那么a会被排列到b之前。
- 如果compareFunction(a,b)等于0,a和b的相对位置不变。
- 如果compareFunction(a,b)大于0,b会被排列到a之前。
- compareFunction(a,b)必须总是对相同的输入返回相同的比较结果,否则排序的结果将会是不确定的。
所以上面解决方案采用了 sort((a, b) => a - b)。
另外这里还用到了arr.every(callback[, thisArg])。every()方法测试数组的所有元素是否都通过了指定函数的测试。
every()方法为数组中的每个元素执行一次callback函数,直到它找到一个使callback返回false的元素。如果发现一个这样的元素,every方法将会立即返回false。否则,callback为每一个元素返回true,every就会返回true。
用了every方法,就不用和我一样傻傻的做比较判断真假了
ps:
说到every,也要说一说some方法,some和every都是在需要break的场景下,有相同的作用,只不过两者有一个不同:
- every:碰到return false的时候,循环终止
- some:碰到return true的时候,循环终止