code war 天天一练(2)

Instruction

code war 天天一练(2)

code war 天天一练(2)

看题就要看一会,大致意思就是:比较数组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方法,就不用和我一样傻傻的做比较判断真假了code war 天天一练(2)

ps:

说到every,也要说一说some方法,some和every都是在需要break的场景下,有相同的作用,只不过两者有一个不同:

  • every:碰到return false的时候,循环终止
  • some:碰到return true的时候,循环终止

 附: codewar-该习题练习地址