-1

这是我的第一个问题,因为我正在学习编程几天但现在我被困住了

任务:

你在这个 kata 中的目标是实现一个差异函数,它从另一个列表中减去一个列表并返回结果。

它应该从 list 中删除所有值a,这些值存在于 list 中,并b保持其顺序。

arrayDiff([1,2],[1]) == [2]
如果一个值存在于 中b,则必须从另一个中删除它的所有出现:

arrayDiff([1,2,2,2,3],[2]) == [1,3]

我的解决方案:

function arrayDiff(a, b) {  
for (var j = 0; j < a.length; j++) {
  for (var i = 0; i < b.length; i++) {
    if(a[j] == b[i]) {
      a.splice(j);
      j--;
      }
    }
  }
  return a;
}

看起来我做错了什么并且发生了奇怪的事情:有时测试全部变成红色,有时所有 BUT 1 测试都变成红色,而休息是绿色。总是让我失望的是:

应该通过基本测试

awas [1,2], bwas [1]: 期望[]深度相等[ 2 ]

4

3 回答 3

0

您的函数的问题是,您在 for 循环中更改数组的长度,该循环使用 a 的长度。这会导致某些索引被跳过。

function arrayDiff(a, b) {  
for (var j = 0; j < a.length; j++) {
  for (var i = 0; i < b.length; i++) {
    if(a[j] == b[i]) {
      // here you change the size of a.
      a.splice(j);
      j--;
      }
    }
  }
  return a;
}

要解决此问题,请创建一个临时数组,在其中推送 a 中不包含在 b 中的所有值。

function arrayDiff(a,b) {
    // Temporary array, containing all values from a, which are not contained in b
    let diffArray = [];
    // Looping over a
    for(let i = 0; i < a.length; i++) {
        // Per default we say that b does not contain a
        let bContainsAValue = false;
        // Loop over b
        for(let y = 0; y < b.length; y++) {
            // If any value in b is the same as the current value from a, we set bContainsAValue to true
            if(a[i] === b[y]) bContainsAValue = true;
        }
        // Now only if bContainsAValue is still false, meaning it does not contain the a value, we push this value into our temporary array
        if(!bContainsAValue) diffArray.push(a[i]);
    }
    // In the end we return the temporary array
    return diffArray;
}

这是我的方法,它更简单并且使用了一些数组函数:

function arrayDiff(a, b) {
    // Filter entire a array, only keep the value if b does not contain that value
    return a.filter(val => !b.includes(val));
}
于 2021-08-31T06:47:44.963 回答
0

您可以使用数组的内置方法,并将其与集合结合使用。类似于以下内容:

function diff(a, b) {
  const left = a.filter(item => !b.includes(item))
  const right = b.filter(item => !a.includes(item))
  return Array.from(new Set([].concat(left, right)))
}

以你的例子

diff([1,2,2,2,3],[2]) // returns [1, 3]
diff([1,2],[1]) // returns [2]

该函数也应该是可传递的,即在计算差异时参数顺序应该无关紧要。所以翻转参数应该返回相同的结果。

diff([2], [1,2,2,2,3]) // returns [1, 3]
diff([1],[1,2]) // returns [2]
于 2021-08-31T07:39:25.117 回答
0

这是一种简单的方法,您可以通过混合ES6来解决代码中的错误。

由于您的数组长度在循环中发生变化,因此您可以delete array[j]在不更改数组长度或元素索引的情况下删除该值。根据这个答案

如果您只想使 index 处的元素i不再存在,但又不希望其他元素的索引发生变化:

这会将重复值替换为undefinedundefined然后你可以用一行删除所有元素

a.filter(Boolean)

在这里参考更多

function arrayDiff(a, b) {
  for (var j = 0; j < a.length; j++) {
    for (var i = 0; i < b.length; i++) {
      if (a[j] == b[i]) {
        delete a[j];
      }
    }
  }
  console.log(a.filter(Boolean))
  return a.filter(Boolean);
}
arrayDiff([1, 2], [1])
arrayDiff([1, 2, 2, 2, 3], [2])

这是一个使用 ES6 的单班轮,没有任何嵌套或突变

const arrayDiff = (a, b) => a.filter(item => !b.includes(item))
console.log(arrayDiff([1, 2], [1]))
console.log(arrayDiff([1, 2, 2, 2, 3], [2]))

于 2021-08-31T07:08:02.107 回答