0
0

More than 3 years have passed since last update.

Python 3 イテレータ型の要素に2つの値が同時に出現する回数を数える

Last updated at Posted at 2020-06-05

イテレータ型(リストやタプル)の要素にある2つの要素が同時に出現する回数を数えるコードです。イテレータ型の要素の組み合わせ(itertools.combination)、イミュータブルセット(frozenset)、キーを指定したsortedのサンプルコードでもあります。

コード

count_colocation2.py
import itertools
import typing
from itertools import chain


def count_colocation2(
        iteriter: typing.Iterable
        ) -> typing.Dict[frozenset, int]:
    """
    イテレータ型(リストやタプル)の要素にある2つの要素が同時に出現する回数を数える。
    """
    if not isinstance(iteriter, typing.Iterable):
        raise TypeError()
    # 組み合わせを準備する
    comb = itertools.combinations(frozenset(chain.from_iterable(iteriter)), 2)
    comb = [frozenset(item) for item in comb]
    # 順に調べて組み合わせの存在する数を加算
    d = {key: 0 for key in comb}
    for entry in iteriter:
        for pair in comb:
            t = tuple(pair)
            if t[0] in entry and t[1] in entry:
                d[pair] += 1
    return d

1.py
from pprint import pp

from count_colocation2 import count_colocation2

ll = [
        ["a", "b", "c"],
        ["d", "e", "f"],
        ["a", "d", "f"],
        ["b", "d", "f"],
    ]

coloc2 = count_colocation2(ll)
# 値を降順でソート
pp(sorted(coloc2.items(), key=lambda item: item[1], reverse=True))

"""
[(frozenset({'f', 'd'}), 3),
 (frozenset({'f', 'e'}), 1),
 (frozenset({'f', 'b'}), 1),
 (frozenset({'f', 'a'}), 1),
 (frozenset({'d', 'e'}), 1),
 (frozenset({'d', 'b'}), 1),
 (frozenset({'d', 'a'}), 1),
 (frozenset({'b', 'a'}), 1),
 (frozenset({'b', 'c'}), 1),
 (frozenset({'a', 'c'}), 1),
 (frozenset({'f', 'c'}), 0),
 (frozenset({'b', 'e'}), 0),
 (frozenset({'e', 'a'}), 0),
 (frozenset({'e', 'c'}), 0),
 (frozenset({'d', 'c'}), 0)]
"""

備考

frozenset

frozensetsetのイミュータブル版です。setaddupdateで内容を変更できますが、frozensetは変更できません。一方、frozensetはハッシュが取得できるので辞書のキーになれます。

# 次の行をコメント解除するとエラーが発生します。
# print(hash(set(["a", "b", "c"])))
# TypeError: unhashable type: 'set'

# 正常に完了します。
print(hash(frozenset(["a", "b", "c"])))

同じ辞書のキーとなれるイミュータブル型にtupleがあります。tupleは要素の順番を区別しますが、frozensetは区別しません。

typing.Sequencetyping.Iterable

Pythonにはlisttuplesetfrozensetのようなクラスがありますが、これらは共通の機能で分類できます。listtupleはインデックスでアクセスできることからシーケンス型(typing.Sequence)に分類されます。また、listtuplesetfrozensetはイテレーターを提供することからtyping.Iterableに分類されます。

typing.Sequencetyping.Iterableは型として定義されており、型ヒントで使用する他、isinstanceissubclassでも使用できます。

イテレータ型の組み合わせタプルのリスト

itertools.combinationsによりイテレータ型(typing.Iterable)の要素から任意の数の組み合わせタプルのリストが作成できます。

set/frozensetの要素へのアクセス

set/frozensetはインデックス[index]ではアクセスできません。list()tuple()で一度listtupleに変換すればアクセスできます。イテレータ型ではあるのでforは使用できます。

辞書の非破壊的ソート

sorted()key=...にラムダ式を指定して辞書を非破壊的にソートできます。辞書のキーと値のペアはdict.items()で取得することに注意してください。dictそのものをsortedに渡すとキー名がsorted()の対象となります。

キーでソート
sorted(dict.items(), key=lambda item: item[0])                # 昇順
sorted(dict.items(), key=lambda item: item[0], reverse=True)  # 降順
値でソート
sorted(dict.items(), key=lambda item: item[1])                # 昇順
sorted(dict.items(), key=lambda item: item[1], reverse=True)  # 降順
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0