Pythonでリストを比較

Modified: | Tags: Python, リスト

Pythonで2つのリストを比較・判定する方法について説明する。タプルについても最後に述べる。

リストの大小関係(順序比較)

2つのリストの大小関係・順序を<, <=, >, >=で比較した結果は以下のように決定される。

順序比較をサポートしているコレクションの順序は、最初の等価でない要素の順序と同じになります (例えば、 [1,2,x] <= [1,2,y]x <= y と同じ値になります)。 対応する要素が存在しない場合、短い方のコレクションの方が先の順序となります (例えば、 [1,2] < [1,2,3] は真です)。 6. 式 (expression) - 値の比較 — Python 3.11.3 ドキュメント

先頭の要素から順に比較され、最初の等価でない要素の比較結果がリスト自体の比較結果になる。

print([1, 2, 3] < [1, 2, 100])
# True

print([1, 2, 3] < [1, 2, 0])
# False

対応する要素が無い場合、要素数が少ない方が先の順序(小さい)とみなされる。

print([1, 2] < [1, 2, 3])
# True

等価でない要素がある場合は要素数は関係なく、あくまでも先頭から順に比較される。

print([100] < [1, 2, 3])
# False

文字列など他の型を要素とするリストでも同様。

print(['a', 'b', 'c'] < ['a', 'b', 'x'])
# True

対応する要素が比較できない型の場合はエラーとなる。

# print([100] < ['a'])
# TypeError: '<' not supported between instances of 'int' and 'str'

リストに対する==(等価比較)

リストに対する==での比較は、対応する要素を順番に比較してすべて等価であったときにTrueを返す。そうでない場合はFalse

print([1, 2, 3] == [1, 2, 3])
# True

print([1, 2, 3] == [3, 2, 1])
# False

print([1, 2, 3] == [1, 2])
# False

各要素は==で比較される。型が異なっていても値が等価であればTrue。型も含めて完全に一致するか判定する方法は後述。

print([1, 2, 3] == [True, 2.0, 3 + 0j])
# True

!===の否定。

print([1, 2, 3] != [1, 2, 3])
# False

print([1, 2, 3] != [3, 2, 1])
# True

print([1, 2, 3] != [1, 2])
# True

print([1, 2, 3] != [True, 2.0, 3 + 0j])
# False

なお、isはオブジェクトの同一性を判定する。2つのリストが同じオブジェクトを指していればTrue。そうでなければFalseとなる。

l1 = [1, 2, 3]
l2 = [1, 2, 3]
print(l1 is l2)
# False

l1_assign = l1
print(l1_assign)
# [1, 2, 3]

print(l1 is l1_assign)
# True

リストの完全一致を判定

2つのリストが完全一致しているかを判定するには、例えば以下のような関数を定義する。ここでは、2つのリストの要素数が等しく、先頭から順に対応する要素の値も型も一致していることを完全一致と呼んでいる。

def lists_match(l1, l2):
    if len(l1) != len(l2):
        return False
    return all(x == y and type(x) == type(y) for x, y in zip(l1, l2))

print(lists_match([1, 2, 3], [1, 2, 3]))
# True

print(lists_match([1, 2, 3], [1, 2]))
# False

print(lists_match([1, 2, 3], [True, 2.0, 3 + 0j]))
# False

集合として処理(部分一致、部分・上位集合など)

リストを集合(set)に変換すると、集合演算が可能。

部分一致

2つのリストが部分的に一致しているか、すなわち、共通する要素が少なくとも1つあるかを判定するには、setisdisjoint()メソッドを使う。引数にはsetだけでなくリストなどの他のイテラブルオブジェクトも指定できる。

isdisjoint()は共通の要素を持たないときにTrueを返す。したがって、その否定notが部分一致するかの判定に等しい。

l1 = [1, 2, 3]
l2 = [3, 4, 5]
l3 = [5, 6, 7]
print(not set(l1).isdisjoint(l2))
# True

print(not set(l1).isdisjoint(l3))
# False

判定だけでなく、複数のリストに共通する要素・共通しない要素を抽出したい場合は以下の記事を参照。

部分集合・上位集合(すべて含まれるか)

集合Aのすべての要素が集合Bに含まれているとき、AはBの部分集合、BはAの上位集合という。部分集合か、上位集合かを判定するには、setissubset(), issuperset()メソッドを使う。

一方のリストの要素が他方のリストにすべて含まれるか、という判定が可能。

l1 = [1, 2]
l2 = [1, 2, 3]
print(set(l1).issubset(l2))
# True

print(set(l2).issuperset(l2))
# True

その他の集合演算

集合setを利用すると、一方のリストから他方のリストに含まれる要素を取り除いて差分を抽出する、といった処理などもできる。

l1 = [1, 2, 3, 4, 5]
l2 = [2, 3, 4]
print(list(set(l1) - set(l2)))
# [1, 5]

集合setについての詳細は以下の記事を参照。

タプルの比較

ここまでリストの比較について説明したが、タプルの比較についても同様。

print((1, 2, 3) < (1, 2, 100))
# True

print((1, 2, 3) == (1, 2, 3))
# True

print(set((1, 2)).issubset((1, 2, 3)))
# True

リストとタプルを<, <=, >, >=で比較するとエラーになる。list()またはtuple()で型を揃える必要がある。

l = [1, 2, 3]
t = (1, 2, 3)

# print(l <= t)
# TypeError: '<=' not supported between instances of 'list' and 'tuple'

print(l <= list(t))
# True

リストとタプルを==で比較するとFalseを返す。list()またはtuple()で型を揃えれば、対応する要素ごとの比較が可能。

print(l == t)
# False

print(l == list(t))
# True

関連カテゴリー

関連記事