Python CollectionsモジュールのCounter


Collectionsモジュールのカウンタの使い方と実装原理については、pythonの正式に複写する.を参照してください.
Counter内部実装原理
1.オブジェクトの作成
Counterはdictを継承するクラスで、hashable項目をカウントします.
したがってdictには、必要に応じてcounterクラスを上書きまたは展開する属性もあります.Counter Classの味(?)2番目のディレクトリで、追加したオーバーシュートまたはオーバーシュート方法について説明します.
class Counter(dict):
    	...
カウンタオブジェクトは、さまざまなパラメータで作成できます.
c = Counter()  
# 비어있는 Counter
c = Counter('gallahad')   
# iterable로부터 Counter를 생성
c = Counter({'a': 4, 'b': 2}) 
# mapping으로부터 Counter 생성
c = Counter(a=4, b=2)  
# 위와 동일한 결과로, keyword args로 생성
これは、Counterクラスのinit関数を表示するときに、次のパラメータが実装されるためです.
 def __init__(self, iterable=None, /, **kwds):
        super().__init__()
        self.update(iterable, **kwds)
2.書き換えカウンタ
以前、Counterクラスはdictを継承し、上書きまたは拡張関数を有していた.
カウントされた各オブジェクトの数がCounterクラスの主要な役割であると考える場合は、各関数がなぜこんなに誇張されているのかを自然に理解できます.代表的な誇張事例をいくつか見てみましょう
update
上の__init__update関数をもっと詳しく見てみましょう.
ここでのupdateはdictのupdateと似ていますが、追加したキーが各count値を置換していない点が異なります.これは、replaceよりも既存のcount値をcountクラスに追加する方が直感的であるためです.△この単語は最終的に何回出てきたのですか.)
実装ロジックでは、dictionary形式で指定されたパラメータが既存のcountに追加され、list形式で指定された場合、_count_elements関数を使用して各要素の出現回数が計算されます.
 def update(self, iterable=None, /, **kwds):
	 if iterable is not None:
            if isinstance(iterable, _collections_abc.Mapping):
                if self:
                    self_get = self.get
                    for elem, count in iterable.items():
                        self[elem] = count + self_get(elem, 0)
                else:
                    # fast path when counter is empty
                    super().update(iterable)
            else:
                _count_elements(self, iterable)
        if kwds:
            self.update(kwds)
_count_elements関数は、このカウンタ関数がdictを継承する特徴を持つため、get関数があるため、自分でマッピングされ、iterableから要素が現れるたびに1増加することがわかります.
def _count_elements(mapping, iterable):
    mapping_get = mapping.get
    for elem in iterable:
        mapping[elem] = mapping_get(elem, 0) + 1
most_common
1つの関数で、出現回数が最も多い要素から出現回数が最も多いn番目の要素を返します.
nがない場合は、出現回数の降順で並べ替え、nがある場合はheapqを使用します.self.items()がheapqに渡されているため、各鍵とその出現回数の値ペアがリストを返すことが予想される.
def most_common(self, n=None):
        # Emulate Bag.sortedByCount from Smalltalk
        if n is None:
            return sorted(self.items(), key=_itemgetter(1), reverse=True)

        # Lazy import to speedup Python startup time
        import heapq
        return heapq.nlargest(n, self.items(), key=_itemgetter(1))
fromkeys
dictの作成時には、fromkeysメソッドで鍵リストを簡単に巡回してdictシーケンスを生成することもできます.counterでは、鍵に手動で値を追加することを避ける必要があります.valueはkeyの出現回数に基づいて決定しなければならないからです.例えば、Counter.fromkeys('aaabbc', v=2)のようにディックシーケンスを生成すると、aが2回現れたという奇妙なデータが表示される.したがって、fromkeys関数が呼び出されると、counterクラスは、以下に示すようにNotImplementedErrorに直接発行されます.
@classmethod
    def fromkeys(cls, iterable, v=None):
        raise NotImplementedError(
            'Counter.fromkeys() is undefined.  Use Counter(iterable) instead.')
Counter使用例
文字列sが小文字(「a」から「z」)からなり、使用頻度が最も高い文字を返すソリューション関数を実現します.
ただし、最大2文字以上のアルファベットを使用すると、アルファベット順に文字列が返されます.
def solution(s):
	# s= "aabbcdd"
    c = Counter(s.lower())
    # Counter가 문자열(iterable)로 초기화(__init__)되면서 내부적으로 update를 호출하여 각 letter와 등장횟수를 key,value로 가지고 있는 상태
    # Counter({'a': 2, 'b': 2, 'c': 1, 'd': 2})
    mc = c.most_common(1)[0][1]
    # [('a',2)] 에서 2를 추출 
    mc_words = [letter for letter, val in c.items() if val == mc]
    mc_words.sort()
    # 2와 동일한 값을 가지는 value의 key들을 모아서 알파벳 순으로 sort 
    return ''.join(mc_words)
    # abd
Counterのmost_common関数は、nが与えられたとき、heapq.nlargest(n, self.items(), key=_itemgetter(1))によってn対の最大値のリストを返す.したがって、[0][1]と同じインデックスを用いてmost_commonから返される値から出場回数を抽出することができる.
リファレンス🚩
上記の例を少し修正して、特定のアルファベットの順序を早めたい場合は、どうすればいいですか?
この場合、単純呼sort()では所望の結果が得られない.この場合、sort条件をそれぞれ作成するために、各アルファベットの優先度をvalueに設定するdictを作成しました.
△もっといい意見があれば、教えてください.😀)
「コードは次のとおりです.」d'優先度の高い例.
def solution(s):
    # s= "aabbcdd"
    c = Counter(s.lower())
    mc_words = [letter for letter, val in c.items() if val == c.most_common(1)[0][1]]
    mc_words.sort()
    # 여기까지는 동일

    words = dict(zip(mc_words, range(len(mc_words))))
    # {'a': 0, 'b': 1, 'd': 2}
    
    for word in words.keys():
        if word == 'd':
            words['d'] = -1
    # {'a': 0, 'b': 1, 'd': -1}

    answer = ''.join(k for k, v in sorted(words.items(), key=itemgetter(1)))
    return answer
    # dab
前述したCounterのmost_commonでは、最初のインデックスの値に基づいてソートされた次の部分が表示され、いくつかのヒントが得られていることに注意してください.
if n is None:
      return sorted(self.items(), key=_itemgetter(1), reverse=True)