note.nkmk.me

Pythonで複数のリストに共通する・しない要素とその個数を取得

Posted: 2018-05-22 / Modified: 2020-02-18 / Tags: Python, リスト

Pythonで複数のリスト(配列)から共通する要素・共通しない要素を抽出し、その個数をカウントするには、各リストを集合型setに変換し集合演算を行う。

ここでは以下の内容について説明する。

  • 複数のリストから共通する要素とその個数を取得
  • 複数のリストから共通しない要素とその個数を取得
  • 複数のリストからユニークな要素とその個数を取得

集合set型および集合演算についての詳細は以下の記事を参照。

一つのリストから重複する要素を抽出したい場合は以下の記事を参照。

以下の3つのリストを例とする。

l1 = ['a', 'b', 'c']
l2 = ['b', 'c', 'd']
l3 = ['c', 'd', 'e']

例はリストだが、タプルでも同様の処理が可能。

スポンサーリンク

複数のリストから共通する要素とその個数を取得

共通部分は&演算子で取得できる。なおset型は順序を持たないので、どういう順番で出力されるかは不定。

l1_l2_and = set(l1) & set(l2)
print(l1_l2_and)
# {'c', 'b'}

print(type(l1_l2_and))
# <class 'set'>

set型をリストlist型に変換したい場合はlist()を使う。上述のようにsetに変換すると順序は保持されないので、再度リストに戻した場合も元のリストの順序は保持されない(偶然同じ順序になることはある)。

l1_l2_and_list = list(l1_l2_and)
print(l1_l2_and_list)
# ['c', 'b']

print(type(l1_l2_and_list))
# <class 'list'>

個数はlen()で取得可能。

print(len(l1_l2_and))
# 2

3個以上の場合も同様。

l1_l2_l3_and = set(l1) & set(l2) & set(l3)
print(l1_l2_l3_and)
# {'c'}

複数のリストから共通しない要素とその個数を取得

対称差集合(二つの集合のどちらか一方にのみ含まれる要素の集合)は^演算子で取得できる。

l1_l2_sym_diff = set(l1) ^ set(l2)
print(l1_l2_sym_diff)
# {'a', 'd'}

上の例と同じく、リスト化したい場合はlist()、個数を取得したい場合はlen()を使う。

print(list(l1_l2_sym_diff))
# ['a', 'd']

print(len(l1_l2_sym_diff))
# 2

元のリストが3個の場合に^演算子を使うと、すべてのリストに共通する要素も含まれるので注意。

l1_l2_l3_sym_diff = set(l1) ^ set(l2) ^ set(l3)
print(l1_l2_l3_sym_diff)
# {'c', 'a', 'e'}

いずれかのリストにのみ含まれる要素を抽出したい場合は、すべてのリストを連結したリストから個数が1個の要素を抽出する方法がある。リスト内包表記およびリストから要素の個数を取得するメソッドcount()を使う。

set()を使うことで、同じ値の要素の個数を繰り返しカウントする無駄を防ぐことができる。

l_all = l1 + l2 + l3
print(l_all)
# ['a', 'b', 'c', 'b', 'c', 'd', 'c', 'd', 'e']

print(set(l_all))
# {'d', 'b', 'a', 'c', 'e'}

l_all_only = [x for x in set(l_all) if l_all.count(x) == 1]
print(l_all_only)
# ['a', 'e']

なお、この方法だと元のリストが重複する要素を持っていた場合、その要素も除外される。

l1_duplicate = ['a', 'a', 'b', 'c']

l_duplicate_all = l1_duplicate + l2 + l3
l_duplicate_all_only = [x for x in set(l_duplicate_all) if l_duplicate_all.count(x) == 1]
print(l_duplicate_all_only)
# ['e']

最初に各リストごとに重複した要素を削除してユニークな要素のみのリストにしてから処理すれば、各リストにのみ含まれる要素を抽出可能。

l_unique_all = list(set(l1_duplicate)) + list(set(l2)) + list(set(l3))
print(l_unique_all)
# ['c', 'b', 'a', 'c', 'b', 'd', 'c', 'd', 'e']

l_uniaues_all_only = [x for x in set(l_unique_all) if l_unique_all.count(x) == 1]
print(l_uniaues_all_only)
# ['a', 'e']

複数のリストからユニークな要素とその個数を取得

複数のリストから重複を取り除きユニークな(一意な)値の要素を抽出したい場合は、リストをすべて足し合わせてから集合set()型に変換する。

l1_l2_or = set(l1 + l2)
print(l1_l2_or)
# {'c', 'b', 'a', 'd'}

print(list(l1_l2_or))
# ['c', 'b', 'a', 'd']

print(len(l1_l2_or))
# 4

3個以上の場合も同様。

l1_l2_l3_or = set(l1 + l2 + l3)
print(l1_l2_l3_or)
# {'d', 'b', 'a', 'c', 'e'}

元のリストの順序を保持したい場合は以下の記事を参照。

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事