1. ホーム
  2. パイソン

[解決済み] リストのすべての要素が条件に一致するかどうかを確認するには?

2022-04-05 08:54:08

質問

2万件ほどのリストから構成されるリストがあります。各リストの3番目の要素をフラグとして使用しています。私は、少なくとも1つの要素のフラグが0である限り、このリスト上でいくつかの操作を行いたい、それはのようなものです。

my_list = [["a", "b", 0], ["c", "d", 0], ["e", "f", 0], .....]

最初はフラグがすべて0なので、whileループを使って、少なくとも1つの要素のフラグが0であるかどうかをチェックしています。

def check(list_):
    for item in list_:
        if item[2] == 0:
            return True
    return False

もし check(my_list) が返されます。 True そして、私は自分のリストに取り組み続けます。

while check(my_list):
    for item in my_list:
        if condition:
            item[2] = 1
        else:
            do_sth()

実は、my_listの要素を繰り返しながら削除したかったのですが、繰り返しながら項目を削除することはできません。

オリジナルのmy_listにはフラグがなかった。

my_list = [["a", "b"], ["c", "d"], ["e", "f"], .....]

繰り返しながら要素を削除することができないので、このようなフラグを考案したのです。しかし my_list には多くの項目が含まれており while ループは for をループさせ、多くの時間を消費しています。何かいい方法はないでしょうか?

どのように解決するのですか?

ここでのベストアンサーは all() これは、この状況に対応する組み込み関数です。これを ジェネレータ式 を使えば、欲しい結果をきれいに効率よく出すことができます。例えば

>>> items = [[1, 2, 0], [1, 2, 0], [1, 2, 0]]
>>> all(flag == 0 for (_, _, flag) in items)
True
>>> items = [[1, 2, 0], [1, 2, 1], [1, 2, 0]]
>>> all(flag == 0 for (_, _, flag) in items)
False

なお all(flag == 0 for (_, _, flag) in items) とは直接的に等価である。 all(item[2] == 0 for item in items) この場合、少し読みやすくなるだけです。

そして、フィルタの例では、リスト内包(もちろん、適宜、ジェネレータ式も使えます)。

>>> [x for x in items if x[2] == 0]
[[1, 2, 0], [1, 2, 0]]

少なくとも1つの要素が0であることを確認したい場合、より良い選択肢は any() の方が読みやすいと思います。

>>> any(flag == 0 for (_, _, flag) in items)
True