Salt la conținutul principal
Modulul 8 · Lecția 3 din 431/36 în curs~12 min
Lecții din modul (3/4)

colecții: Counter și defaultdict

Modulul collections adaugă tipuri de date specializate care extind colecții încorporate. Cele trei cele mai utilizate: Counter, defaultdict, namedtuple.

Counter: numărarea frecvenței

Python
from collections import Counter

parole = ["mela", "pera", "mela", "kiwi", "mela", "pera"]
c = Counter(parole)
# Counter({'mela': 3, 'pera': 2, 'kiwi': 1})

c["mela"]            # 3
c["banana"]          # 0   (default for missing keys, NO KeyError)
c.most_common(2)     # [('mela', 3), ('pera', 2)]

Funcționează și pe șiruri de caractere (numărează caracterele):

Python
Counter("ciao mondo")
# Counter({'o': 2, 'c': 1, 'i': 1, 'a': 1, ' ': 1, 'm': 1, 'n': 1, 'd': 1})

Acceptă operațiuni asemănătoare seturilor pentru numărătoare (+, -, &, |) — foarte util pentru agregarea numărătorilor din diferite surse.

defaultdict: dict cu implicit automat

Un dict care, atunci când accesați o cheie lipsă, o creează apelând a fabrica.

Python
from collections import defaultdict

gruppi = defaultdict(list)        # factory = list (empty list)
for nome in ["Ada", "Linus", "Ada", "Grace"]:
    gruppi[nome].append(1)
# defaultdict(list, {'Ada': [1, 1], 'Linus': [1], 'Grace': [1]})

Fără defaultdict, ar trebui să scrieți:

Python
gruppi = {}
for nome in [...]:
    if nome not in gruppi:
        gruppi[nome] = []
    gruppi[nome].append(1)

Fabrici comune: list, int (implicit 0), set, dict.

namedtuple: tupluri cu nume de câmpuri

O modalitate ușoară de a crea clase de înregistrare imuabile. Este un tuplu, dar cu acces la câmp după nume.

Python
from collections import namedtuple

Punto = namedtuple("Punto", ["x", "y"])
p = Punto(3, 4)
p.x          # 3 (access by name)
p[0]         # 3 (access by index, still a tuple)
p.x + p.y    # 7

# typical use: return multiple values from a function
def divisione(a, b):
    Risultato = namedtuple("Risultato", ["quoziente", "resto"])
    return Risultato(a // b, a % b)

r = divisione(17, 5)
r.quoziente   # 3
r.resto       # 2

(Pentru cazuri mai sofisticate există și dataclasses începând cu 3.7 - vezi M9.)

namedtuple: înregistrări ușoare imuabile

Modulul collections exportă și namedtuple, care vă permite să construiți rapid obiecte ușoare asemănătoare clasei pentru a stoca date structurate fără a scrie constructori sau metode standard:

Python
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y)

Încearcă

Exercițiu#python.m8.l3.e1
Încercări: 0Se încarcă…

Având în vedere lista `cuvinte = ['mela', 'pera', 'mela', 'kiwi', 'mela', 'pera']`, calculați cel mai frecvent cuvânt din `top` ca șir. Evaluează `top`.

Se încarcă editorul...
Afișează indiciu

Counter(...).most_common(1) returnează [(cuvânt, număr)].

Soluție disponibilă după 3 încercări

Exercițiu de revizuire

Exercițiu#python.m8.l3.e2
Încercări: 0Se încarcă…

Având în vedere `inscrierile studenților = [('Ada', 'mate'), ('Linus', 'fisica'), ('Ada', 'storia'), ('Grace', 'mate')]`, construiți `courses_per_student` ca o listă implicită. Evaluați `dict(cursuri_per_student)`.

Se încarcă editorul...
Afișează indiciu

defaultdict(list) apoi pentru s, c în înscrieri.

Soluție disponibilă după 3 încercări

Provocare suplimentară

Exercițiu#python.m8.l3.e3
Încercări: 0Se încarcă…

Importați \`Counter\` din \`colecții\`. Numărați frecvența caracterelor din șirul \`text = "abracadabra"\`. Stocați contorul în \`char_counter\` și evaluați-l.

Se încarcă editorul...
Afișează indiciu

Counter ia șirul ca parametru și numără aparițiile fiecărei litere.

Soluție disponibilă după 3 încercări