2012-01-29 65 views
6

在蟒蛇(2.7)一个列表中,我们可以这样做:删除从另一个

>>> a = [1, 2, 3] 
>>> b = [4 , 5] 
>>> a + b 
[1, 2, 3, 4, 5] 

然而,我们不能做一个 - B。

由于python几乎所有东西都有些酷,在你看来什么是最蟒蛇式的做 - b,

类似的问题的字典,既不能做a + b或a - b,其中a和b都是字典。谢谢。

+8

'[1,2,3,1,2,1] - [1,2]'的结果是什么? – JJJ 2012-01-29 12:50:42

+0

@Juhana灿烂的问题。这将是:[3]。 – dublintech 2012-01-29 12:57:23

+4

然后我会说为什么不''[3,1,2,1]'? – 2012-01-29 13:02:32

回答

11

你可以带套做:

>>> s = set([1,2,3] + [4,5]) 
>>> s - set([4, 5]) 
{1, 2, 3} 

当然是一组主要的差别不能包含重复的元素。

+2

python中的'set'不一定保留其元素的顺序 – 2012-01-29 13:23:19

+2

'set',绝对是最好的事 – juliomalegria 2012-01-29 15:09:57

5

我会做:

>>> a = [1, 2, 3] 
>>> b = [2, 3] 
>>> filter(lambda x: x not in b, a) 
[1] 

或使用列表理解

[x for x in a if x not in b] 

,它可以做了字典一样。

Set定义了运营商-和方法differencesymmetric_difference。如果您打算广泛使用该操作,请使用set而不是list或dict。

+3

这就是'O(n * m)' - 所以如果你的列表不包含任何重复的元素,那么最好使用集合和'-'运算符。 – ThiefMaster 2012-01-29 12:54:06

+0

当然。这就是为什么我写了“如果你打算广泛使用......”:) – 2012-01-29 13:27:24

2

答案取决于所需的语义a - b

如果你只是想的第一要素,然后切片是自然的方式来做到这一点:

In [11]: a = [1, 2, 3] 

In [12]: b = [4 , 5] 

In [13]: ab = a + b 

In [14]: ab[:len(a)] 
Out[14]: [1, 2, 3] 

如果,另一方面,你要删除的第一个列表的元素没有在第二发现列表:

In [15]: [v for v in ab if v not in b] 
Out[15]: [1, 2, 3] 

第二类型的操作的更自然表示使用集:

In [18]: set(ab) - set(b) 
Out[18]: set([1, 2, 3]) 

请注意,通常这不会保留元素的排序(因为集合是无序的)。如果排序是非常重要的,并且b很可能是长,转换b成一组可以提高性能:

In [19]: bset = set(b) 

In [20]: [v for v in ab if v not in bset] 
Out[20]: [1, 2, 3] 

对于字典,已经存在一个在就地“增加”操作。它叫做dict.update()

1

y = set(b)
aminusb = filter(lambda p: p not in y,a)

+1

这是O(n + m),虽然使用'lambda'使得这个解决方案有点慢 – 2012-01-29 13:21:44

3

我会尝试[x for x in a if a not in b]

+1

这就是'O(n * m) – 2012-01-29 13:20:30

+0

这是正确的,但它仍然有点pythonesque。 – phimuemue 2012-01-29 14:24:37

+0

pythonesque ?? pythonic? – juliomalegria 2012-01-29 15:09:07

1

试试这个:

def list_sub(lst1, lst2): 
    s = set(lst2) 
    return [x for x in lst1 if x not in s] 

list_sub([1, 2, 3, 1, 2, 1, 5], [1, 2]) 
> [3, 5] 

这是一个O(n+m)解决了因这样的事实,它使用预先计算set,所以成员查找将是快速的。此外,它将保留原始元素的顺序并删除重复项。

0

订单不会被保留,但它有你想要的结果:

>>> def list_diff(a, b): 
...  return list(set(a) - set(b)) 
... 
>>> print list_diff([1, 2, 3, 1, 2, 1], [1, 2]) 
[3] 
0

这里是我的最佳选择,一是涉及到使用的for循环的其他转换设置。在小单子大小循环的情况下是可以接受的,可以看出对于10列表大小,

In [65]: d1 = range(10) 

In [66]: d2 = range(1) 

In [67]: %timeit [x for x in d1 if x not in d2] 
1000000 loops, best of 3: 827 ns per loop 

In [68]: %timeit list(set(d1)-set(d2)) 
1000000 loops, best of 3: 1.25 µs per loop 

但是如果列表尺寸足够大,那么你应该使用设置,

In [69]: d1 = range(10000) 

In [70]: d2 = range(1000) 

In [71]: %timeit [x for x in d1 if x not in d2] 
10 loops, best of 3: 105 ms per loop 

In [72]: %timeit list(set(d1)-set(d2)) 
1000 loops, best of 3: 566 µs per loop 
相关问题