2010-06-02 102 views
1

我想比較兩個列表。通常這不是問題,因爲我通常使用嵌套for循環並將交集附加到新列表中。在這種情況下,我需要從A.刪除A的交點和BPython - 替代list.remove(x)?

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

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

我的目標是比較A和B以及從A中刪除甲交點B,即,刪除A [0] [0]在這種情況下。

我嘗試:

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)拋出一個ValueError。

回答

9

如果可能的話(這意味着如果爲了和你有「子列表」沒關係的事實),我先flatten the lists,創建sets然後你可以很容易地從A刪除元素在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']) 

或訂單和A事項結構,你可以做(​​感謝和學分THC4k):

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

但請注意:的假設下,這隻能是AB將名單總是名單。

+0

@ THC4k:如果要提供儘可能回答您的意見,我會改變我的答案回原來的一個。 – 2010-06-02 13:49:00

+2

不,你的是偉大的,我只是「希望」,列表中有一個很好的理由;-) – 2010-06-02 14:15:13

1

編輯:要在這種情況下使用remove,在這種情況下不能從列表a中直接刪除j('ab'),因爲它是一個嵌套列表。您將不得不使用A.remove(['ab'])或​​A.remove([j])來完成此操作。

另一種可能性是pop(int)方法。所以A.pop(指數)實際上也應該起作用。

來源:http://docs.python.org/tutorial/datastructures.html

+0

? 'j'始終是'A'中列表的一個元素。這不是一個索引。 – 2010-06-02 13:56:34

+0

哎呀,編輯答案反映了這一點。 – Tyler 2010-06-02 14:21:47

4

使用集和itertools天真的方法。你可以調整這進一步根據您的要求:

#!/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']]