Làm cách nào để kiểm tra xem có thứ gì đó (không) trong danh sách trong Python không?
Giải pháp rẻ nhất và dễ đọc nhất là sử dụng in
toán tử (hoặc trong trường hợp cụ thể của bạn, not in
). Như đã đề cập trong tài liệu,
Các nhà khai thác in
và not in
kiểm tra thành viên. x in s
đánh giá
True
nếu x
là một thành viên của s
, và False
nếu không. x not in s
trả về phủ định của x in s
.
Ngoài ra,
Toán tử not in
được định nghĩa là có giá trị thực nghịch đảo của in
.
y not in x
là logic giống như not y in x
.
Đây là vài ví dụ:
'a' in [1, 2, 3]
# False
'c' in ['a', 'b', 'c']
# True
'a' not in [1, 2, 3]
# True
'c' not in ['a', 'b', 'c']
# False
Điều này cũng hoạt động với các bộ dữ liệu, vì các bộ dữ liệu có thể băm được (do hậu quả của thực tế là chúng cũng bất biến):
(1, 2) in [(3, 4), (1, 2)]
# True
Nếu đối tượng trên RHS định nghĩa một __contains__()
phương thức, in
sẽ gọi bên trong nó, như đã lưu ý trong đoạn cuối của phần So sánh của các tài liệu.
... in
và not in
, được hỗ trợ bởi các loại có thể lặp lại hoặc thực hiện
__contains__()
phương thức. Ví dụ: bạn có thể (nhưng không nên) làm điều này:
[3, 2, 1].__contains__(1)
# True
in
ngắn mạch, vì vậy nếu phần tử của bạn ở đầu danh sách, hãy in
đánh giá nhanh hơn:
lst = list(range(10001))
%timeit 1 in lst
%timeit 10000 in lst # Expected to take longer time.
68.9 ns ± 0.613 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
178 µs ± 5.01 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Nếu bạn muốn làm nhiều hơn là chỉ kiểm tra xem một mục có trong danh sách hay không, có các tùy chọn:
list.index
có thể được sử dụng để lấy chỉ mục của một mục. Nếu yếu tố đó không tồn tại, a ValueError
được nâng lên.
list.count
có thể được sử dụng nếu bạn muốn đếm số lần xuất hiện.
Vấn đề XY: Bạn đã xem xét set
s?
Hãy tự hỏi mình những câu hỏi sau:
- Bạn có cần kiểm tra xem một mục có trong danh sách nhiều lần không?
- Là kiểm tra này được thực hiện trong một vòng lặp, hoặc một chức năng được gọi nhiều lần?
- Các mặt hàng bạn đang lưu trữ trong danh sách của bạn có thể băm không? IOW, bạn có thể gọi
hash
cho họ?
Nếu bạn trả lời "có" cho những câu hỏi này, bạn nên sử dụng set
thay thế. Một in
bài kiểm tra thành viên trên list
s là độ phức tạp thời gian O (n). Điều này có nghĩa là python phải thực hiện quét tuyến tính danh sách của bạn, truy cập từng phần tử và so sánh nó với mục tìm kiếm. Nếu bạn đang làm điều này nhiều lần hoặc nếu danh sách lớn, thao tác này sẽ phải chịu chi phí.
set
mặt khác, các đối tượng băm giá trị của chúng để kiểm tra tư cách thành viên liên tục. Kiểm tra cũng được thực hiện bằng cách sử dụng in
:
1 in {1, 2, 3}
# True
'a' not in {'a', 'b', 'c'}
# False
(1, 2) in {('a', 'c'), (1, 2)}
# True
Nếu bạn không may là phần tử bạn đang tìm kiếm / không tìm kiếm nằm ở cuối danh sách của bạn, python sẽ quét danh sách cho đến cuối. Điều này là hiển nhiên từ thời gian dưới đây:
l = list(range(100001))
s = set(l)
%timeit 100000 in l
%timeit 100000 in s
2.58 ms ± 58.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
101 ns ± 9.53 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
Xin nhắc lại, đây là một tùy chọn phù hợp miễn là các yếu tố bạn lưu trữ và tìm kiếm có thể băm được. IOW, chúng sẽ phải là các loại bất biến, hoặc các đối tượng thực hiện __hash__
.
3 -1 > 0 and (4-1 , 5) not in []
⤇True
do đó các lỗi không phải là một trong những ưu tiên điều hành.