2012-01-29 51 views
6
khác

Trong python (2.7) chúng ta có thể làm:Loại bỏ một danh sách từ

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

Tuy nhiên chúng ta không thể làm một - b.

Vì python dường như có thứ gì đó tuyệt vời cho gần như mọi thứ, python-esque nhất để làm a - b, theo ý kiến ​​của bạn là gì?

Câu hỏi tương tự cho từ điển, không thể thực hiện a + b, hoặc a - b, trong đó a và b là cả hai từ điển. Cảm ơn.

+8

Kết quả sẽ là gì đối với '[1, 2, 3, 1, 2, 1] - [1, 2]'? – JJJ

+0

@Juhana Câu hỏi nổi bật. Nó sẽ là: [3]. – dublintech

+4

Sau đó, tôi muốn nói tại sao không '[3, 1, 2, 1]'? –

Trả lời

11

Bạn có thể làm điều này với bộ:

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

Sự khác biệt chính của khóa học là một bộ không thể chứa các thành phần trùng lặp.

+2

Một 'bộ' trong python không nhất thiết phải giữ nguyên thứ tự của các phần tử của nó –

+2

' set', chắc chắn điều tốt nhất để làm – juliomalegria

5

tôi sẽ làm:

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

hoặc sử dụng danh sách comprehensions

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

Và nó có thể được thực hiện theo cách tương tự cho từ điển.

Set đã xác định toán tử - và phương thức differencesymmetric_difference. Nếu bạn đang có kế hoạch sử dụng rộng rãi các hoạt động đó, hãy sử dụng thiết lập thay vì danh sách hoặc dict.

+3

Đó là 'O (n * m)' - vì vậy nếu danh sách của bạn không chứa bất kỳ phần tử trùng lặp nào, tập hợp sử dụng tốt hơn và toán tử '-'. – ThiefMaster

+0

Tất nhiên. Đó là lý do tại sao tôi viết "Nếu bạn định sử dụng rộng rãi ..." :) –

2

Câu trả lời tùy thuộc vào ngữ nghĩa mong muốn của a - b.

Nếu bạn chỉ muốn các yếu tố đầu tiên, sau đó cắt là cách tự nhiên để làm điều đó:

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] 

Nếu, mặt khác, bạn muốn loại bỏ các yếu tố của danh sách đầu tiên không tìm thấy trong lần thứ hai danh mục:

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

loại thứ hai hoạt động được một cách tự nhiên hơn thể hiện bằng bộ:

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

Lưu ý rằng nói chung điều này không bảo vệ thứ tự của các phần tử (vì các bộ không có thứ tự). Nếu đặt hàng là quan trọng, và b có khả năng là dài, chuyển đổi b thành một tập thể cải thiện hiệu suất:

In [19]: bset = set(b) 

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

Đối với từ điển, đã tồn tại một "Ngoài" hoạt động tại chỗ. Nó được gọi là dict.update().

1

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

+1

Đó là O (n + m), mặc dù sử dụng 'lambda' làm cho giải pháp này chậm hơn một chút –

3

tôi sẽ cố gắng [x for x in a if a not in b].

+1

Đó là' O (n * m) ' –

+0

Đó là chính xác, nhưng dù sao nó hơi pythonesque. – phimuemue

+0

pythonesque ?? ... pythonic? – juliomalegria

1

Hãy thử điều này:

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] 

Đây là một giải pháp O(n+m) do thực tế rằng nó sử dụng một precomputed set, vì vậy tìm kiếm thành viên sẽ được nhanh chóng. Ngoài ra, nó sẽ bảo vệ thứ tự của các yếu tố ban đầu và loại bỏ các bản sao.

0

thứ tự không được bảo quản, nhưng nó có kết quả bạn muốn:

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

Dưới đây là lựa chọn ưa thích của tôi, một trong những liên quan đến việc sử dụng vòng lặp for chuyển đổi khác để thiết lập. Trong trường hợp của kích thước danh sách nhỏ cho vòng lặp là chấp nhận được như có thể thấy trong một kích thước danh sách của 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 

Tuy nhiên, nếu kích thước danh sách là đủ lớn, sau đó bạn nên có lẽ sử dụng thiết lập,

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 
Các vấn đề liên quan