Jak korzystać z licznika Pythona z modułu Collections

W niniejszym poradniku zgłębisz tajniki wykorzystania obiektu counter, dostępnego w module collections języka Python.

Podczas operowania na rozbudowanych sekwencjach danych w Pythonie, takich jak listy czy ciągi znaków, często zachodzi potrzeba zidentyfikowania i zliczenia wystąpień poszczególnych elementów.

Chociaż słownik Pythona doskonale sprawdza się w roli struktury danych do takich zadań, klasa Counter z modułu collections oferuje bardziej eleganckie rozwiązanie. Counter tworzy licznik – swego rodzaju słownik, który przechowuje elementy sekwencji i ich częstotliwość występowania.

W ciągu kilku najbliższych minut dowiesz się, jak:

  • Wykorzystywać obiekt counter w Pythonie.
  • Stworzyć słownik w Pythonie do przechowywania danych o liczbie wystąpień elementów w strukturze iterowalnej.
  • Przekształcić tradycyjny słownik, używając licznika Pythona, dzięki uproszczonej składni.
  • Wykonywać operacje takie jak aktualizacja i odejmowanie elementów, a także znajdowanie części wspólnych między dwoma obiektami licznika.
  • Pobierać najczęściej występujące elementy z licznika za pomocą metody most_common().

Zacznijmy naszą podróż!

Moduł Collections i klasa Counter w Pythonie

Do przechowywania elementów i ich liczby w strukturze iterowalnej często wykorzystuje się słownik. Elementy są reprezentowane jako klucze, a ich liczebność jako odpowiadające im wartości.

Ponieważ klasa Counter jest częścią wbudowanego modułu collections, możesz ją zaimportować do swojego skryptu, używając poniższej komendy:

from collections import Counter

Po zaimportowaniu klasy Counter, możesz utworzyć instancję obiektu licznika w następujący sposób:

<obiekt_licznika> = Counter(iterowalny_obiekt)

Gdzie:

  • iterowalny_obiekt oznacza dowolną poprawną strukturę iterowalną Pythona, taką jak lista, ciąg znaków czy krotka.
  • Elementy w strukturze iterowalnej muszą być haszowalne.

Teraz, gdy znamy podstawy tworzenia obiektów licznika z dowolnych struktur iterowalnych, przejdźmy do praktyki.

Przykłady z tego poradnika znajdziesz w tym GitHub Gist.

Jak utworzyć obiekt licznika z iterowalnych obiektów Pythona

Zdefiniujmy ciąg znaków, na przykład „renesans”, i przypiszmy go do zmiennej word:

>>> word = "renesans"

Naszym celem jest stworzenie słownika, w którym każda litera z ciągu word będzie miała przypisaną liczbę swoich wystąpień w tym ciągu. Jednym ze sposobów osiągnięcia tego jest użycie pętli for, jak pokazano niżej:

>>> letter_count = {}
>>> for letter in word:
...     if letter not in letter_count:
...         letter_count[letter] = 0
...     letter_count[letter] += 1
...
>>> letter_count
{'r': 1, 'e': 2, 'n': 2, 'a': 2, 's': 2, 'i': 1, 'c': 1}

Przeanalizujmy krok po kroku, co robi ten fragment kodu:

  • Inicjalizuje pusty słownik Python o nazwie letter_count.
  • Iteruje po ciągu znaków word.
  • Sprawdza, czy dana litera znajduje się już w słowniku letter_count.
  • Jeśli litery nie ma w słowniku, dodaje ją z wartością początkową 0, a następnie zwiększa tę wartość o 1.
  • Dla każdego napotkanego wystąpienia litery w słowie, wartość przypisana do tej litery jest zwiększana o 1.
  • Proces ten jest kontynuowany, dopóki nie przejdziemy przez wszystkie znaki w ciągu.

Zatem samodzielnie skonstruowaliśmy słownik letter_count, wykorzystując pętlę for do iteracji po ciągu znaków.

Teraz wykorzystajmy klasę Counter z modułu collections. Wystarczy przekazać ciąg znaków word do funkcji Counter(), aby otrzymać słownik letter_count bez konieczności iterowania w pętli.

>>> from collections import Counter
>>> letter_count = Counter(word)
>>> letter_count
Counter({'e': 2, 'n': 2, 'a': 2, 's': 2, 'r': 1, 'i': 1, 'c': 1})

Obiekt licznika jest również słownikiem Pythona. Możemy to sprawdzić, wykorzystując wbudowaną funkcję isinstance():

>>> isinstance(letter_count,dict)
True

Jak widać, isinstance(letter_count, dict) zwraca wartość True, co potwierdza, że obiekt licznika letter_count jest instancją klasy słownika Pythona.

Modyfikacja obiektu licznika

Dotychczas nauczyliśmy się, jak tworzyć obiekty licznika z ciągów znaków Pythona.

Możemy również modyfikować obiekty licznika, aktualizując je o elementy z innych struktur iterowalnych lub odejmując od nich zawartość innych struktur.

Aktualizacja licznika elementami z innej struktury iterowalnej

Zainicjujmy kolejny ciąg znaków, nazwijmy go another_word:

>>> another_word = "musowanie"

Załóżmy, że chcielibyśmy zaktualizować obiekt licznika letter_count o elementy z ciągu another_word.

Możemy w tym celu skorzystać z metody update() dostępnej w obiekcie licznika letter_count.

>>> letter_count.update(another_word)
>>> letter_count
Counter({'e': 7, 'n': 3, 's': 3, 'c': 3, 'r': 2, 'a': 2, 'f': 2, 'i': 1, 'v': 1})

Jak widzimy na wyjściu, obiekt licznika został zaktualizowany o litery i liczbę ich wystąpień z ciągu another_word.

Odejmowanie elementów z innej struktury iterowalnej

Teraz odejmijmy elementy z ciągu another_word od obiektu letter_count. W tym celu możemy skorzystać z metody subtract(). Wywołanie .subtract() odejmie wartości odpowiadające elementom z od .

Odejmijmy zawartość another_word od letter_count.

>>> letter_count.subtract(another_word)
>>> letter_count
Counter({'e': 2, 'n': 2, 'a': 2, 's': 2, 'r': 1, 'i': 1, 'c': 1, 'f': 0, 'v': 0})

Możemy zauważyć, że wartości odpowiadające literom z ciągu another_word zostały odjęte, ale nowo dodane klucze „f” i „v” nie zostały usunięte, tylko ich wartość wynosi teraz 0.

Uwaga: W powyższym przykładzie przekazaliśmy do metody subtract() ciąg znaków Pythona. Możemy jednak przekazać również obiekt licznika Pythona lub inny obiekt iterowalny.

Część wspólna dwóch obiektów licznika w Pythonie

Czasami może zajść potrzeba znalezienia części wspólnej dwóch obiektów licznika, aby zidentyfikować klucze, które występują w obu z nich.

Utwórzmy obiekt licznika, nazwijmy go letter_count_2, z ciągu another_word „musowanie”.

>>> another_word = "musowanie"
>>> letter_count_2 = Counter(another_word)
>>> letter_count_2
Counter({'e': 5, 'f': 2, 'c': 2, 'r': 1, 'v': 1, 's': 1, 'n': 1})

Możemy wykorzystać prosty operator &, aby znaleźć część wspólną między letter_count i letter_count_2.

>>> letter_count & letter_count_2
Counter({'e': 2, 'r': 1, 'n': 1, 's': 1, 'c': 1})

Jak widzimy, otrzymaliśmy klucze i liczbę wystąpień wspólnych dla obu słów. Zarówno słowo „renesans”, jak i „musowanie” zawierają dwa wystąpienia litery „e” oraz po jednym wystąpieniu „r”, „n”, „s” i „c”.

Wyszukiwanie najczęściej występujących elementów za pomocą metody most_common

Kolejną powszechną operacją na obiekcie licznika jest wyszukiwanie najczęściej występujących elementów.

Aby pobrać listę k najczęściej występujących elementów, możemy użyć metody most_common() na obiekcie licznika. W tym przykładzie wywołujemy most_common() na obiekcie letter_count, aby znaleźć trzy najczęściej występujące litery.

>>> letter_count.most_common(3)
[('e', 2), ('n', 2), ('a', 2)]

Widzimy, że litery „e”, „n” i „a” występują w słowie „renesans” po dwa razy.

Jest to szczególnie przydatne, gdy licznik zawiera dużą liczbę pozycji i chcemy pracować z najczęściej występującymi kluczami.

Podsumowanie

Oto krótkie podsumowanie tego, czego nauczyliśmy się w tym poradniku:

  • Klasa Counter z wbudowanego modułu collections Pythona może być wykorzystana do tworzenia słownika zliczającego liczbę wystąpień każdego elementu w dowolnej strukturze iterowalnej. Należy upewnić się, że wszystkie elementy w strukturze iterowalnej są haszowalne.
  • Możesz aktualizować zawartość jednego obiektu licznika Pythona zawartością innego obiektu licznika lub dowolnego innego obiektu iterowalnego, wykorzystując metodę update() o składni: licznik1.update(licznik2). Zauważ, że zamiast licznika2 możesz użyć dowolnej struktury iterowalnej.
  • Jeżeli chcesz usunąć zawartość jednej struktury iterowalnej ze zaktualizowanego licznika, możesz skorzystać z metody subtract(): licznik1.subtract(licznik2).
  • Aby znaleźć elementy wspólne dla dwóch obiektów licznika, możesz wykorzystać operator &. Biorąc pod uwagę dwa liczniki licznik1 i licznik2, licznik1 & licznik2 zwróci część wspólną obu liczników.
  • Aby pobrać k najczęściej występujących elementów w liczniku, możesz użyć metody most_common(). Wywołanie licznik.most_common(k) zwróci k najczęściej występujących elementów wraz z ich liczbą wystąpień.

Na koniec zapoznaj się z default dict, kolejną przydatną klasą z modułu collections. Możesz użyć default dict zamiast zwykłego słownika Pythona do obsługi brakujących kluczy.