Bagaimana menerapkan operator logika ke semua elemen dalam daftar python

90

Saya memiliki daftar boolean dengan python. Saya ingin DAN (atau ATAU atau BUKAN) mereka dan mendapatkan hasilnya. Kode berikut berfungsi tetapi tidak terlalu pythonic.

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

Ada saran tentang bagaimana membuatnya lebih pythonic dihargai.

Robert Christie
sumber

Jawaban:

176

Logis anddi semua elemen di a_list:

all(a_list)

Logis ordi semua elemen di a_list:

any(a_list)

Jika Anda merasa kreatif, Anda juga dapat melakukan:

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)

perlu diingat bahwa itu tidak dievaluasi dalam korsleting, sementara built-in adalah ;-)

cara lucu lainnya:

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

dan satu lagi:

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

dan kita bisa terus sepanjang hari, tapi ya, cara pythonic adalah menggunakan alldan any:-)

Ngomong-ngomong, Python tidak memiliki eliminasi rekursi ekor, jadi jangan mencoba menerjemahkan kode LISP secara langsung ;-)

fortran
sumber
8
operator.and_ adalah bitwise dan operator &, bukan logika dan.
Ants Aasma
1
untungnya True dan False (seperti yang diinginkan op) dicor ke 1 dan 0 masing-masing, jadi operator bitwise bekerja sebagai logis ^ _ ^
fortran
6
Menjelaskan banyak versi yang berlebihan, tetapi tidak memberikan sintaks untuk jawaban yang benar.
jwg
2
tidak setuju apa pun yang Anda inginkan, ada di faq: stackoverflow.com/privileges/vote-down
fortran
2
Perhatikan bahwa reduce()dalam functoolssejak Python 3.0
Duncan WP
33

ANDing dan ORing itu mudah:

>>> 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

Mencatat juga cukup mudah:

>>> [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]

Tentu saja, bagaimana Anda akan menggunakan hasil tersebut mungkin memerlukan beberapa aplikasi menarik dari teorema DeMorgan.

Jason Baker
sumber
4
Jika Anda ingin hubungan pendek dari varian not, cukup gunakan ekspresi generator: all(not x for x in some_list)(tapi itu sama dengan not any(some_list)(ekspresi yang cukup alami, ya?)).
u0b34a0f6ae
16

Reduce bisa melakukan ini:

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

Seperti yang disebutkan fortran, semua adalah cara paling ringkas untuk melakukannya. Tapi kurangi jawaban pertanyaan yang lebih umum "Bagaimana menerapkan operator logika ke semua elemen dalam daftar python?"

Frank Krueger
sumber
4
mengurangi tidak akan hilang, AFAIK. sedang dipindahkan ke modul functools, dari posisi sebelumnya di namespace global
Eli Bendersky
1
@eliben: Mengapa berbicara tentang Python 3 dalam bentuk masa depan? mengurangi masih ada . reduceada functools.reduce di Python 3
u0b34a0f6ae
Jika Anda menghapus , True, jawaban ini akan menjadi satu-satunya jawaban yang benar-benar setara dengan kode pertanyaan, untuk daftar non-boolean.
Thomas Ahle
10

Idiom untuk operasi semacam itu adalah menggunakan reducefungsi (global dengan Python 2.X, dalam modul functoolsdengan Python 3.X) dengan operator biner yang sesuai baik yang diambil dari operatormodul atau dikodekan secara eksplisit. Dalam kasus Anda, ituoperator.and_

reduce(operator.and_, [True, True, False])
Eli Bendersky
sumber
4

Berikut solusi lain:

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

def my_or(a_list):
    return True in a_list

ANDing semua elemen akan mengembalikan True jika semua elemen adalah True, maka tidak ada False dalam daftar. ORing serupa, tetapi harus mengembalikan True jika setidaknya satu nilai True ada dalam daftar.

Xarts
sumber
0

Seperti yang ditunjukkan jawaban lain, ada banyak cara untuk menyelesaikan tugas ini. Berikut solusi lain yang menggunakan fungsi dari pustaka standar:

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)
mipadi
sumber