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
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.