views:

182

answers:

3

Hi,

I wish to compare two lists. Generally this is not a problem as I usually use a nested for loop and append the intersection to a new list. In this case, I need to delete the intersection of A and B from A.

 A = [['ab', 'cd', 'ef', '0', '567'], ['ghy5'], ['pop', 'eye']]

 B = [['ab'], ['hi'], ['op'], ['ej']]

My objective is to compare A and B and delete A intersection B from A, i.e., delete A[0][0] in this case.

I tried:

def match():
    for i in A:
        for j in i:
            for k in B:
                for v in k:
                    if j == v:
                        A.remove(j)

list.remove(x) throws a ValueError.

+8  A: 

If possible (meaning if the order and the fact that you have "sublists" does not matter), I would first flatten the lists, create sets and then you can easily remove the elements from A that are in B:

>>> from itertools import chain
>>> A = [['ab', 'cd', 'ef', '0', '567'], ['ghy5'], ['pop', 'eye']]
>>> B = [['ab'], ['hi'], ['op'], ['ej']]
>>> A = set(chain(*A))
>>> B = set(chain(*B))
>>> A-B
set(['ghy5', 'eye', 'ef', 'pop', 'cd', '0', '567'])

Or if the order and structure of A matters, you can do (thanks and credits to THC4k):

>>> remove = set(chain(*B))
>>> A = [[x for x in S if x not in remove] for S in A].

But note: This only works under the assumption that A and B will be always lists of lists.

Felix Kling
@THC4k: If you want to provide your comment as answer, I will change my answer back to the original one.
Felix Kling
No, your's is great, I just "hope" that there is a good reason for that list of lists ;-)
THC4k
+1  A: 

Edit: To use remove in a situation like this, you can't directly remove j ('ab') in this case from the list a, since it is a nested list. You would have to use A.remove(['ab']) or A.remove([j]) to accomplish this.

Another possibility is the pop(int) method. So A.pop(index) should actually work as well.

Source: http://docs.python.org/tutorial/datastructures.html

Tyler
? `j` is always an element of the lists in `A`. It is not an index.
Felix Kling
Oops, edited the answer to reflect that.
Tyler
+4  A: 

A naive approach using sets and itertools. You can tweak this further according to your requirements:

#!/usr/bin/env python

a = [['ab', 'cd', 'ef', '0', '567'], ['ghy5'], ['pop', 'eye']]
b = [['ab'], ['hi'], ['op'], ['ej']]

from itertools import chain

# this results in the intersection, here => 'ab'
intersection = set(chain.from_iterable(a)).intersection(
    set(chain.from_iterable(b)))

def nested_loop(iterable):
    """
    Loop over arbitrary nested lists.
    """
    for e in iterable:
        if isinstance(e, list):
            nested_loop(e)
        else:
            if e in intersection:
                iterable.remove(e)
    return iterable

print nested_loop(a)
# => 
# [['cd', 'ef', '0', '567'], ['ghy5'], ['pop', 'eye']]
The MYYN