2009-11-24 17 views
46

私はPythonでブール値のリストを持っています。私はそれらをAND(OR OR NOT)して結果を得たいです。以下のコードは動作しますが、非常にpythonicではありません。Pythonリストのすべての要素に論理演算子を適用する方法

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

どのようにもっとpythonicになるかについてのご意見があります。

a_list内のすべての要素間

答えて

105

論理and

a_list内のすべての要素間
all(a_list) 

論理or

any(a_list) 

クリエイティブ感じた場合、あなたも行うことができます。

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) 

組み込み関数は、別の面白い方法;-)

ある一方で、それらは、短絡に評価されていないことに注意してください:

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 

さらに別:

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 

私たちは一日中続きますが、はい、pythonic方法はallany :-)を使用することです:

By the wa Y、Pythonはない末尾再帰の除去を持っているので、直接;-)

+7

operator.and_はビット単位で演算子&は論理和と論理和ではありません。 –

+1

luckly真と偽(opが必要とする)はそれぞれ1と0にキャストされるので、ビット演算子は論理的に動作します^^^ – fortran

+0

価値があります... 2.5+しかしバックポートは非​​常に簡単です。 –

10

Reduceはこれを行うことができますLISPコードを変換しようとしないでください:言及したFORTRANのよう

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

、すべてが行うための最も簡潔な方法ですがそれ。しかし、より一般的な質問 "すべての要素に論理演算子を適用する方法は、Pythonのリストの答えを減らす?

+4

reduceがなくなっていないので、 'reduce()'は 'functools'にあることに注意してください、AFAIK。それはfunctoolsモジュールに移動されています。グローバル名空間の前の位置から移動しています –

+1

@eliben:なぜ将来の時制でPython 3について話しますか? *まだ減らしている*。 'reduce'は' functools.reduce' *です。Python 3 * – u0b34a0f6ae

+0

'、True'を削除すると、この答えは疑問のコードと実際に等価な唯一のものになります。 –

31

AND演算と論理和は簡単です:

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

注目にも非常に簡単です:あなたはドモルガンの定理のいくつかの興味深いアプリケーションが必要になることがあり、それらの結果を使用する方法もちろん

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

、。

+4

あなたはnot variantの短循環を望むなら、単純にジェネレータ式を使います: 'all(xはsome_listのxではありません)'(しかし、 'not any(some_list)'と同じです。 ))。 – u0b34a0f6ae

0

他の回答が示すように、このタスクを達成するには複数の方法があります。ここで、標準ライブラリから関数を使用する別の解決策は次のとおり

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

そのような操作のイディオムは(Pythonの3.Xにおけるモジュールfunctoolsに、Pythonの2.xでグローバル)reduce関数を使用することで適切なバイナリとオペレータはoperatorモジュールから取得するか、明示的にコード化します。あなたのケースでは、それはoperator.and_

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

だここで別のソリューションです:すべての要素が真である場合

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

def my_or(a_list): 
    return True in a_list 

AND演算は、すべての要素が故に偽リストで、Trueを返しません。 ORingは似ていますが、少なくとも1つのTrue値がリストに存在する場合はTrueを返します。

関連する問題