2015-08-24 14 views
20

Tôi có hai danh sách boolean, ví dụ:Toán tử Python AND trên hai danh sách boolean - làm cách nào?

x=[True,True,False,False] 
y=[True,False,True,False] 

Tôi muốn VÀ các danh sách này với nhau, với sản lượng dự kiến:

xy=[True,False,False,False] 

Tôi nghĩ rằng biểu x and y sẽ làm việc, nhưng đến khám phá ra rằng nó không: trên thực tế, (x and y) != (y and x)

Sản lượng x and y: [True,False,True,False]

Sản lượng y and x: [True,True,False,False]

Sử dụng danh sách hiểu không có đầu ra chính xác. Whew!

xy = [x[i] and y[i] for i in range(len(x)] 

Tôi không thể tìm thấy bất kỳ tham chiếu nào cho tôi biết toán tử AND sẽ hoạt động như tôi đã thử với x và y. Nhưng thật dễ dàng để thử mọi thứ bằng Python. Ai đó có thể giải thích cho tôi điều gì đang xảy ra với x and y?

Và đây là một chương trình thử nghiệm đơn giản:

import random 
random.seed() 
n = 10 
x = [random.random() > 0.5 for i in range(n)] 
y = [random.random() > 0.5 for i in range(n)] 
# Next two methods look sensible, but do not work 
a = x and y 
z = y and x 
# Next: apparently only the list comprehension method is correct 
xy = [x[i] and y[i] for i in range(n)] 
print 'x  : %s'%str(x) 
print 'y  : %s'%str(y) 
print 'x and y : %s'%str(a) 
print 'y and x : %s'%str(z) 
print '[x and y]: %s'%str(xy) 
+0

x là một danh sách, y là một danh sách. 'x và y' là true nếu và chỉ khi cả hai danh sách không trống (một danh sách trống là 'false-y', tất cả các danh sách không trống là 'truth-y'): đó là' x và y' * không * 'và mỗi phần tử' hoặc quan tâm đến các giá trị khác. – user2864740

Trả lời

26

and chỉ đơn giản là trả về một trong hai người đầu tiên hoặc toán hạng thứ hai, dựa trên giá trị thật của họ. Nếu toán hạng đầu tiên được coi là sai, nó được trả về, ngược lại toán hạng khác được trả về.

Danh sách được coi là đúng khi không để trống, vì vậy cả hai danh sách đều được coi là đúng. Nội dung của chúng không đóng một vai trò nào tại đây.

Vì cả hai danh sách đều không trống, x and y chỉ trả về đối tượng danh sách thứ hai; chỉ khi x là trống rỗng, nó sẽ được trả lại thay vì:

>>> [True, False] and ['foo', 'bar'] 
['foo', 'bar'] 
>>> [] and ['foo', 'bar'] 
[] 

Xem Truth value testing section trong tài liệu Python:

Bất kỳ đối tượng có thể được kiểm tra giá trị thật, để sử dụng trong một điều kiện if hoặc while hoặc là toán hạng của các phép toán Boolean bên dưới. Các giá trị sau đây được coi sai:

[...]

  • bất kỳ chuỗi rỗng, ví dụ, '', (), [].

[...]

Tất cả các giá trị khác được coi là đúng - vì vậy đối tượng của nhiều loại là luôn luôn đúng.

(tôi nhấn mạnh), và Boolean operations section ngay phía dưới rằng:

x and y
nếu x là sai, sau đó x, khác y

Đây là một nhà điều hành ngắn mạch, do đó, nó chỉ đánh giá đối số thứ hai nếu đối số đầu tiên là True.

Bạn thực sự cần phải kiểm tra các giá trị chứa trong danh sách một cách rõ ràng. Bạn có thể làm như vậy với một danh sách hiểu, như bạn phát hiện ra. Bạn có thể viết lại nó với zip() function để ghép lên các giá trị:

[a and b for a, b in zip(x, y)] 
+1

cảm ơn lời giải thích tuyệt vời và đặc biệt. lặp lại điều tôi đã thấy "nếu x là sai, sau đó x, khác y", nhưng không hoàn toàn grokked. Đây là một trường hợp cho RTFM và tôi nên đọc nó rất cẩn thận! –

2

này nên làm những gì bạn muốn:

xy = [a and b for a, b in zip(x, y)] 

Lý do x and y lợi nhuận yy and x lợi nhuận x là bởi vì các toán tử logic trong trăn trở về kiểm tra giá trị cuối cùng xác định đúng-Ness của biểu thức. Giá trị không rỗng của listTrue và kể từ and yêu cầu cả hai toán hạng để đánh giá True, toán hạng cuối cùng được chọn là toán hạng thứ hai. Tương phản với x or y, sẽ trả về x vì không cần phải kiểm tra y để xác định đúng giá trị của biểu thức.

0

Bạn có thể sử dụng chức năng zip

x=[True,True,False,False] 
y=[True,False,True,False] 
z=[a and b for a,b in zip(x,y)] 
4

and không nhất thiết phải là một nhà điều hành Boolean; nó trả về một trong hai đối số của nó, bất kể kiểu của chúng. Nếu đối số đầu tiên là false-ish (False, số không, hoặc một chuỗi rỗng/container), nó trả về đối số đó. Nếu không, nó trả về đối số thứ hai.

Trong trường hợp của bạn, cả hai xy là danh sách không rỗng, vì vậy đối số đầu tiên luôn luôn là đúng-ish, có nghĩa là lợi nhuận x and yyy and x lợi nhuận x.

6

Bạn có thể sử dụng NumPy:

>>> import numpy as np 
>>> x=np.array([True,True,False,False]) 
>>> y=np.array([True,False,True,False]) 
>>> x & y 
array([ True, False, False, False], dtype=bool) 

NumPy phép hoạt động số và logic trên các mảng như:

>>> z=np.array([1,2,3,4]) 
>>> z+1 
array([2, 3, 4, 5]) 

Bạn có thể thực hiện phép toán và với các nhà điều hành &.

Thay vì một sự hiểu biết danh sách, bạn có thể sử dụng NumPy để tạo ra các mảng boolean trực tiếp như vậy:

>>> np.random.random(10)>.5 
array([ True, True, True, False, False, True, True, False, False, False], dtype=bool) 
0

Thay vì sử dụng

[a and b for a, b in zip(x, y)] 

một chỉ có thể sử dụng khả năng NumPy nhân bool-values:

(np.array(x)*np.array(y)) 
>> array([ True, False, False, False], dtype=bool) 

Hoặc tôi bỏ qua một trường hợp đặc biệt?

0

Ngoài những gì @Martijn Pieters đã trả lời, tôi sẽ chỉ thêm mã sau đây để giải thích các hoạt động andor đang hoạt động.

and trả về giá trị giả đầu tiên gặp phải đối số được đánh giá lần cuối.

Tương tự, or trả lại giá trị thực tế đầu tiên gặp phải đối số được đánh giá lần cuối.

nl1 = [3,3,3,3,0,0,0,0] 
nl2 = [2,2,0,0,2,2,0,0] 
nl3 = [1,0,1,0,1,0,1,0] 
and_list = [a and b and c for a,b,c in zip(nl1,nl2,nl3)] 
or_list = [a or b or c for a,b,c in zip(nl1,nl2,nl3)] 

Giá trị là

and_list = [1, 0, 0, 0, 0, 0, 0, 0]

or_list = [3, 3, 3, 3, 2, 2, 1, 0]

Các vấn đề liên quan