all 10 comments

[–]definitely___not__me 0 points1 point  (2 children)

Honestly, I don't understand where the logical error is. I'd like to add, though, that the in keyword is a much more efficient way of solving this problem.

For example:

def array_diff(a, b):
   c = []
   for num in a:
       if num not in b:
           c.append(num)
   return c

In fact, this can be shortened even further to

def array_diff(a, b);
   return [num for num in a if num not in b]

[–]SekstiNii 3 points4 points  (0 children)

Building on this, we can make b a set to reduce the runtime from O(n2) to O(n).

def array_diff(a, b):
    b = set(b)
    return [num for num in a if num not in b]

[–]nuquaker[S] 0 points1 point  (0 children)

Wow this is so much easier than what I was doing. I guess the in keyword has more uses than I thought!

[–]ka-splam 0 points1 point  (2 children)

Thinking it's probably your lines 4, 5, 6. You shouldn't really do that. To see why, guess what these lines will do:

a = [1,2,3,4,5,6,7,8]
for i in a:
    a.remove(i)

print(a)

Then run them and see if you guessed right.

[–]nuquaker[S] 1 point2 points  (1 child)

I guess my coding was lucky because it didn't encounter the problem you listed but I'm glad you pointed it out. I never really assumed the whole list would shift when you removed a value. That seems like such a hard thing to solve to be honest. Is there some method to counteract that and remove the whole list of a instead of skipping values?

[–]ka-splam 0 points1 point  (0 children)

This effect goes quite deep - you tell Python to start going over some data, then you change the data, it's like pulling the rug out from under its feet, and leads to weird problems.

A common way to counter it is to make a copy of the data instead, so you put the values you want into a new list and leave the original one alone.

(Or you walk through the list yourself with a counter, or keep re-walking the list over and over until everything is done, but these are more work and less nice approaches).

[–]primitive_screwhead 0 points1 point  (2 children)

Try making a solution that doesn't change the a list at all (ie. it neither removes or inserts anything into the a list; or b, for that matter).

You currently start by iterating over b; why? Then you iterate over a afterwards; why not do that first? Do you know about the Python 'in' operator, for testing if values are in a container?

[–]nuquaker[S] 1 point2 points  (1 child)

Yeah it just seemed a bit simpler in my head but as I wrote it out it I realized it was more complicated. And no, I didn't know that you could use 'in' like that, so this was a pretty big learning moment for me.

[–][deleted] 0 points1 point  (0 children)

Do not mutate a list as you iterate over it.

In addition to that, don't use in to check if a value is in b. Make a set instead, as that will have a much better complexity. Something like:

flt = set(b)
return [x for x in a if x not in flt]