Cách áp dụng toán tử logic cho tất cả các phần tử trong danh sách python


90

Tôi có một danh sách các boolean trong python. Tôi muốn VÀ (hoặc HOẶC hoặc KHÔNG) chúng và nhận được kết quả. Đoạn mã sau hoạt động nhưng không quá phức tạp.

def apply_and(alist):
 if len(alist) > 1:
     return alist[0] and apply_and(alist[1:])
 else:
     return alist[0]

Bất kỳ đề xuất nào về cách làm cho nó được đánh giá cao hơn pythonic.

Câu trả lời:


176

Hợp lý andtrên tất cả các phần tử trong a_list:

all(a_list)

Hợp lý ortrên tất cả các phần tử trong a_list:

any(a_list)

Nếu bạn cảm thấy sáng tạo, bạn cũng có thể làm:

import operator
def my_all(a_list):
  return reduce(operator.and_, a_list, True)

def my_any(a_list):
  return reduce(operator.or_, a_list, False)

hãy nhớ rằng những điều đó không được đánh giá trong ngắn mạch, trong khi các tích hợp sẵn ;-)

một cách hài hước khác:

def my_all_v2(a_list):
  return len(filter(None,a_list)) == len(a_list)

def my_any_v2(a_list):
  return len(filter(None,a_list)) > 0

và một số khác:

def my_all_v3(a_list):
  for i in a_list:
    if not i:
      return False
  return True

def my_any_v3(a_list):
  for i in a_list:
    if i:
      return True
  return False

và chúng tôi có thể tiếp tục cả ngày, nhưng có, cách pythonic là sử dụng allany:-)

Nhân tiện, Python không loại bỏ đệ quy đuôi, vì vậy đừng cố dịch mã LISP trực tiếp ;-)


8
operator.and_ là bitwise và toán tử &, không phải là logic và.
Ants Aasma

1
luckly True và False (như op muốn) đều được đúc đến 1 và 0 tương ứng, vì vậy các nhà khai thác Bitwise làm việc như logic ^ _ ^
fortran

6
Đã giải thích rất nhiều phiên bản thừa, nhưng không cung cấp cú pháp cho câu trả lời chính xác thực sự.
jwg

2
không đồng ý bất cứ điều gì bạn muốn, đó là trong câu hỏi thường gặp: stackoverflow.com/privileges/vote-down
fortran

2
Lưu ý rằng reduce()là trong functoolstừ Python 3.0
Duncan WP

33

ANDing và ORing rất dễ dàng:

>>> some_list = [True] * 100
# OR
>>> any(some_list)
True
#AND
>>> all(some_list)
True
>>> some_list[0] = False
>>> any(some_list)
True
>>> all(some_list)
False

NOTing cũng khá dễ dàng:

>>> [not x for x in some_list]
[True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]

Tất nhiên, cách bạn sử dụng các kết quả đó có thể yêu cầu một số ứng dụng thú vị của định lý DeMorgan.


4
Nếu bạn muốn đoản mạch không phải biến thể, chỉ cần sử dụng biểu thức trình tạo: all(not x for x in some_list)(nhưng điều đó giống với not any(some_list)(một biểu thức khá tự nhiên, huh?)).
u0b34a0f6ae

16

Giảm có thể làm điều này:

reduce(lambda a,b: a and b, alist, True)

Như fortran đã đề cập, tất cả là cách cô đọng nhất để làm điều đó. Nhưng giảm các câu trả lời cho câu hỏi chung chung hơn "Làm thế nào để áp dụng một toán tử logic cho tất cả các phần tử trong danh sách python?"


4
giảm không biến mất, AFAIK. nó được di chuyển sang mô-đun functools, từ vị trí trước đây của nó trong không gian tên toàn cầu
Eli Bendersky

1
@eliben: Tại sao lại nói về Python 3 ở thì tương lai? giảm vẫn còn đó . reducefunctools.reduce bằng Python 3
u0b34a0f6ae

Nếu bạn xóa , Truecâu trả lời, câu trả lời này sẽ là câu trả lời duy nhất thực sự tương đương với mã của câu hỏi, cho danh sách không boolean.
Thomas Ahle

10

Thành ngữ cho các hoạt động như vậy là sử dụng reducehàm (toàn cục trong Python 2.X, trong mô-đun functoolstrong Python 3.X) với một toán tử nhị phân thích hợp hoặc được lấy từ operatormô-đun hoặc được mã hóa rõ ràng. Trong trường hợp của bạn, đó làoperator.and_

reduce(operator.and_, [True, True, False])

4

Đây là một giải pháp khác:

def my_and(a_list):
    return not (False in a_list)

def my_or(a_list):
    return True in a_list

ANDing tất cả các phần tử sẽ trả về True nếu tất cả các phần tử là True, do đó không có False trong danh sách. ORing cũng tương tự, nhưng nó sẽ trả về True nếu có ít nhất một giá trị True trong danh sách.


0

Như các câu trả lời khác cho thấy, có nhiều cách để thực hiện nhiệm vụ này. Đây là một giải pháp khác sử dụng các hàm từ thư viện chuẩn:

from functools import partial

apply_and = all
apply_or = any
apply_not = partial(map, lambda x: not x)

if __name__ == "__main__":
    ls = [True, True, False, True, False, True]
    print "Original: ", ls
    print "and: ", apply_and(ls)
    print "or: ", apply_or(ls)
    print "not: ", apply_not(ls)
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.