Làm cách nào để thêm nội dung của một lần lặp vào một tập hợp?


Câu trả lời:


228

Bạn có thể thêm các yếu tố của a listvào setnhư thế này:

>>> foo = set(range(0, 4))
>>> foo
set([0, 1, 2, 3])
>>> foo.update(range(2, 6))
>>> foo
set([0, 1, 2, 3, 4, 5])

2
Chỉ cần nhìn lại phiên thông dịch của tôi và tôi thực sự đã thử nó, nhưng nghĩ rằng nó đã thêm toàn bộ danh sách như là một thành phần của tập hợp vì dấu ngoặc vuông trong biểu diễn của tập hợp. Tôi chưa bao giờ nhận thấy rằng họ được đại diện như thế.
Ian Mackinnon

7
Đại diện đó cho phép bạn dán nó trở lại ngay trong một phiên tương tác, bởi vì hàm settạo lấy một lần lặp làm đối số của nó.
Frank Kuster

3
Lưu ý rằng biểu diễn chỉ là ví dụ {1, 2, 3}trong Python 3 trong khi đó là set([1, 2, 3])ở Python 2.
Radon Rosborough

40

Vì lợi ích của bất kỳ ai có thể tin, ví dụ như thực hiện aset.add()trong một vòng lặp sẽ có hiệu suất cạnh tranh với việc thực hiện aset.update(), đây là một ví dụ về cách bạn có thể kiểm tra niềm tin của mình một cách nhanh chóng trước khi công khai:

>\python27\python -mtimeit -s"it=xrange(10000);a=set(xrange(100))" "a.update(it)"
1000 loops, best of 3: 294 usec per loop

>\python27\python -mtimeit -s"it=xrange(10000);a=set(xrange(100))" "for i in it:a.add(i)"
1000 loops, best of 3: 950 usec per loop

>\python27\python -mtimeit -s"it=xrange(10000);a=set(xrange(100))" "a |= set(it)"
1000 loops, best of 3: 458 usec per loop

>\python27\python -mtimeit -s"it=xrange(20000);a=set(xrange(100))" "a.update(it)"
1000 loops, best of 3: 598 usec per loop

>\python27\python -mtimeit -s"it=xrange(20000);a=set(xrange(100))" "for i in it:a.add(i)"
1000 loops, best of 3: 1.89 msec per loop

>\python27\python -mtimeit -s"it=xrange(20000);a=set(xrange(100))" "a |= set(it)"
1000 loops, best of 3: 891 usec per loop

Có vẻ như chi phí cho mỗi mục của cách tiếp cận vòng lặp lớn hơn BA lần so với updatecách tiếp cận.

Sử dụng |= set()chi phí khoảng 1,5 lần những gì updatelàm được nhưng một nửa của việc thêm từng mục riêng lẻ vào một vòng lặp.


14

Bạn có thể sử dụng hàm set () để chuyển đổi một lần lặp thành một tập hợp, sau đó sử dụng toán tử cập nhật tập hợp tiêu chuẩn (| =) để thêm các giá trị duy nhất từ ​​tập hợp mới của bạn vào tập hợp hiện có.

>>> a = { 1, 2, 3 }
>>> b = ( 3, 4, 5 )
>>> a |= set(b)
>>> a
set([1, 2, 3, 4, 5])

5
Việc sử dụng .updatecó lợi ích là đối số có thể là bất kỳ lặp đi lặp lại nhất thiết phải là một tập hợp không giống như RHS của |=toán tử trong ví dụ của bạn.
tzot

1
Điểm tốt. Đây chỉ là một lựa chọn thẩm mỹ vì set () có thể chuyển đổi một lần lặp thành một tập hợp, nhưng số lượng tổ hợp phím là như nhau.
gbc

Tôi chưa bao giờ thấy nhà điều hành đó trước đây, tôi sẽ thích sử dụng nó khi nó bật lên trong tương lai; cảm ơn!
eipxen

1
@eipxen: Có sự |kết hợp, &giao nhau và ^để có được các yếu tố nằm trong một hoặc khác nhưng không phải cả hai. Nhưng trong một ngôn ngữ được gõ động, đôi khi rất khó đọc mã và biết các loại vật thể bay xung quanh, tôi cảm thấy do dự khi sử dụng các toán tử này. Một số người không nhận ra chúng (hoặc có lẽ thậm chí không nhận ra rằng Python cho phép các toán tử như thế này) có thể bị nhầm lẫn và nghĩ rằng một số hoạt động logic hoặc bit lạ kỳ đang diễn ra. Thật tuyệt nếu các nhà khai thác này cũng làm việc trên các iterables khác ...
ArtOfWarfare 30/03/2015

Chạy một số thử nghiệm thời gian về điều này so với .update()và thêm các yếu tố riêng lẻ trong một vòng lặp. Tìm thấy đó .update()là nhanh hơn. Tôi đã thêm kết quả của mình vào câu trả lời hiện có này: stackoverflow.com/a/4046249/901641
ArtOfWarfare 30/03/2015

4

Chỉ cần cập nhật nhanh, hẹn giờ bằng python 3:

#!/usr/local/bin python3
from timeit import Timer

a = set(range(1, 100000))
b = list(range(50000, 150000))

def one_by_one(s, l):
    for i in l:
        s.add(i)    

def cast_to_list_and_back(s, l):
    s = set(list(s) + l)

def update_set(s,l):
    s.update(l)

kết quả là:

one_by_one 10.184448844986036
cast_to_list_and_back 7.969255169969983
update_set 2.212590195937082

0

Sử dụng danh sách hiểu.

Đoản mạch việc tạo iterable bằng cách sử dụng một danh sách chẳng hạn :)

>>> x = [1, 2, 3, 4]
>>> 
>>> k = x.__iter__()
>>> k
<listiterator object at 0x100517490>
>>> l = [y for y in k]
>>> l
[1, 2, 3, 4]
>>> 
>>> z = Set([1,2])
>>> z.update(l)
>>> z
set([1, 2, 3, 4])
>>> 

[Chỉnh sửa: bỏ lỡ phần đặt câu hỏi]


1
Tôi không thấy bộ nào? Tui bỏ lỡ điều gì vậy?
Ian Mackinnon

-2
for item in items:
   extant_set.add(item)

Đối với hồ sơ, tôi nghĩ rằng khẳng định rằng "Nên có một - và tốt nhất là chỉ có một cách rõ ràng để làm điều đó." là không có thật Nó đưa ra một giả định mà nhiều người có đầu óc kỹ thuật đưa ra, mọi người đều nghĩ giống nhau. Điều gì là hiển nhiên đối với một người không quá rõ ràng đối với người khác.

Tôi sẽ lập luận rằng giải pháp đề xuất của tôi rõ ràng có thể đọc được, và làm những gì bạn yêu cầu. Tôi không tin có bất kỳ bản hit hiệu suất nào liên quan đến nó - mặc dù tôi thừa nhận mình có thể đang thiếu thứ gì đó. Nhưng bất chấp tất cả những điều đó, nó có thể không rõ ràng và thích hợp hơn với một nhà phát triển khác.


Argh! Vòng lặp for nằm trên một dòng giống như định dạng trong câu trả lời của tôi - tôi sẽ không bao giờ làm điều đó. Không bao giờ.
jaydel

Bạn hoàn toàn chính xác. Tôi chỉnh sửa bài để sửa chữa thiệt hại của tôi. Cảm ơn :)
jaydel

9
Bạn đang thiếu điểm aset.update(iterable)vòng lặp ở tốc độ C trong khi for item in iterable: aset.add(item)vòng lặp ở tốc độ Python, với tra cứu phương thức và gọi phương thức (aarrgghh !!) cho mỗi mục.
John Machin

1
Xin lỗi, anh ấy không nói gì về hiệu suất trong câu hỏi của mình nên tôi không lo lắng về điều đó.
jaydel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.