-2

this is my first question as I'm learning programming for few days but now and I'm stuck

Task:

Your goal in this kata is to implement a difference function, which subtracts one list from another and returns the result.

It should remove all values from list a, which are present in list b keeping their order.

arrayDiff([1,2],[1]) == [2]
If a value is present in b, all of its occurrences must be removed from the other:

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

My solution:

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;
}

Looks like I'm doing something wrong and peculiar thing happens: sometimes tests turn all red, sometimes all BUT 1 test turn red, while rest is green. The one that always fails me is:

Should pass Basic tests

a was [1,2], b was [1]: expected [] to deeply equal [ 2 ]

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
jaclaw
  • 11
  • 1
  • 2
  • 2
    Check the [documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice) of `.splice(start, deleteCount, item1, item2, itemN)`, escpecially what `deleteCount` is for and the behavior when its missing. – Andreas Aug 31 '21 at 06:47
  • 'I'm learning programming for few days' and then you use the phrase 'to deeply equal'. It seems you have a very fast brain. I would like to deeply equal it. – JoePythonKing Aug 31 '21 at 07:57
  • @JoePythonKing that's just what the test says ^^ I don't undesrstand the concept of 'deeply equal' myself – jaclaw Aug 31 '21 at 08:43
  • lots of good stuff on this post - https://stackoverflow.com/questions/1187518/how-to-get-the-difference-between-two-arrays-in-javascript – JoePythonKing Aug 31 '21 at 08:51
  • Did my [answer](https://stackoverflow.com/a/68994262/13833218) solve your problem? – Rifky Niyas Sep 01 '21 at 13:41

4 Answers4

1

The problem with your function is, that you change the length of your a array while in a for loop, which uses the length of a. This causes certain index to be skipped.

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;
}

To fix this, create a temporary array, in which you push all values from a, which are not contained in 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;
}

Here is my approach, which is simpler and uses some array functions:

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));
}
Flashtube
  • 209
  • 1
  • 6
  • Thank you for the input @Andreas, I've changed my answer! Let me know if this is fine. – Flashtube Aug 31 '21 at 07:03
  • Thank you @Flashtube I see now that creating a new array is a good solution. I thought that my "j--" will work the same way, apparently it doesn't – jaclaw Aug 31 '21 at 07:37
0

Here is an easy approach that you can take to solve the error in your code with a mix of ES6.

Since your array length changes over the loop, you can use delete array[j] to remove the value without changing the length of the array or the index of elements. According to this answer

If you just want to make the element at index i no longer exist, but you don't want the indexes of the other elements to change:

This replaces the duplicate values with undefined. Then you can remove all the undefined elements with a single line

a.filter(Boolean)

Refer more here

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])

Here's a single liner using ES6 without any nesting or mutation

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]))
Rifky Niyas
  • 1,737
  • 10
  • 25
0

You could use the builtin methods for array, and combine that with the set. Something like the following:

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)))
}

By your example

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

The function should also be transitive, I.e the parameter order should not matter when calculating a difference. So flipping the parameters should return the same result.

diff([2], [1,2,2,2,3]) // returns [1, 3]
diff([1],[1,2]) // returns [2]
pat
  • 5,757
  • 5
  • 25
  • 30
0

This also works:

#  create a function, pass in the listNames as parameters
def array_diff(a, b):
    # create an entity removeNum: the loop through b, to check if it's in list b
    for removeNumber in b:
    #  If removeNum is in b, loop through a as well to check if it's there
        while removeNumber in a:
    #  So, if removeNum is in list a
            try:
    #  Try function to remove it from a... using .remove()
                a.remove(removeNumber)
    #  except to return empty list
            except ValueError:
                return[]
    return a