为什么如果语句在while循环中阻塞?

时间:2019-06-11 11:24:15

标签: javascript arrays loops if-statement

我有一组数字,一堆重复。我需要摆脱它们,所以我放上代码:

  let dup = arr.filter((elem, pos)=> arr.indexOf(elem) !== pos);
  // dup Array contains the duplicate numbers
  arr = arr.filter((elem, pos)=> arr.indexOf(elem) == pos);
  //arr contains the whole array with duplicates
  let i = 0;
  let j = 0;
  while(i<arr.length){
    while(j<dup.length){
      if(arr[i] == dup[j]){
        arr.splice(i, 1);
        //the splice method resets the decrease the index of the array so
        i--;
      };
      j++;
    };
    i++
  }

问题在于if在第一个匹配项之后没有运行。因此数组splice找到并停止了它的第一个重复项。我该如何解决?

3 个答案:

答案 0 :(得分:3)

来自Get all unique values in a JavaScript array (remove duplicates)

const myArray = ['a', 1, 'a', 2, '1'];

const unique = [...new Set(myArray)]; 

// output ["a", 1, 2, "1"]

或作为功能

const unique = [...new Set(myArray)]

答案 1 :(得分:3)

问题在于您永远不会重置j。您需要将其移动到while (i ...)循环内。

let arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
console.log('arr', arr)

let dup = arr.filter((elem, pos)=> arr.indexOf(elem) !== pos);

console.log('dup', dup)

arr = arr.filter((elem, pos)=> arr.indexOf(elem) == pos)
console.log('new arr', arr)


let i = 0;
while(i<arr.length){
  let j = 0;
  while(j<dup.length){
    if(arr[i] == dup[j]){
      arr.splice(i, 1);
      i--;
    };
    j++;
  };
  i++
}

console.log('final arr', arr)

但是有更简单的方法可以做到这一点。

更新

我因不显示任何一种方法而提及更简单的方法而感到兴奋。这是获得相同结果的另一种方法:

const singletons = (
  xs,
  dups = xs .filter ((x, i) => arr .indexOf (x) !== i)
) => xs .filter (x => dups .indexOf (x) < 0)

let arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]

console .log (
  singletons (arr)
)

此版本不会修改您的原始数组,只是返回一个仅包含单例元素的元素(那些元素在原始列表中仅出现一次)。

说明

singletons是一个函数,该函数接受某种类型的元素的数组并返回另一个相同类型的数组。因为该类型不是特定的,所以我使用一个非特定的名称。相当强硬的约定使此xss注意到它是复数形式(即它们的数组)。

dups是在原始元素中重复的元素数组。尽管我将其作为默认参数包含在内,但我们可以像在函数主体中这样轻松地创建它:

const singletons = (xs) => {
  const dups = xs .filter ((x, i) => arr .indexOf (x) !== i)
  return xs .filter (x => dups .indexOf (x) < 0)
}

我没有这样做的唯一原因是,我可能对单一表达式主体过于钟爱,因此避免使用{-}对和return语句。但是,这两种方法之间并没有真正的区别,只是我介绍的方法恰好做了一些我永远都不会依靠的工作:如果提供第二个参数,则是一个值数组,而不是删除重复项,它会从数组中删除所有那些也在第二个元素中的元素,从而使人联想到集合差异函数。

与您的方法相比,此方法的主要优点是它是无损的。它不会改变您的原始数据。除了默认参数外,它也没有赋值,因此状态管理不会引起混淆。 (“ let j == 0放在哪里?”在这里不是有意义的问题。)这使它显得更健壮。

答案 2 :(得分:2)

您需要在第一个while循环内设置j = 0,否则它将仅在第二个while循环中运行一次。

另外,如果我是您,我会使用for循环(特别是array.forEach())代替while,因为它们已经计算了元素的数量。

我对此的解决方案是:

arr.forEach((e, i) => {
    dup.forEach((f, j) => {
        if(e==f){
            arr.splice(i, 1);
        }
    })
});

希望它对您有用。