Skip to content

GROUP BY in Python (itertools.groupby)

Python

In Python, puoi raggruppare elementi consecutivi dello stesso valore in un oggetto iterabile come un elenco con itertools.groupby().

import itertools

l = [0, 0, 0, 1, 1, 2, 0, 0]
print([(k, list(g)) for k, g in itertools.groupby(l)])
# [(0, [0, 0, 0]), (1, [1, 1]), (2, [2]), (0, [0, 0])]

In questo articolo vengono descritti i seguenti contenuti.

  • Vieni a usare itertools.groupby()
  • Specifica una funzione che calcola un valore chiave per ogni elemento:key
  • Aggrega come GROUP BY in SQL
  • Per tupla e archi

Usa collezioni.Contatore per contare il numero di elementi dello stesso valore, in o dal loro ordine, cioè consecutivi non consecutivi.

itertools.groupby() fornisce un iteratore di chiavi e gruppi. I valori non vengono stampati da print().

l = [0, 0, 0, 1, 1, 2, 0, 0]
print(itertools.groupby(l))
# 

Il gruppo è tornato è anche un iteratore. Ad esempio, usa list() per creare un elenco.

Il restituito è esso stesso un iteratore che condivide l’iterabile sottostante con groupby(). Poiché l’origine è condivisa, quando l’oggetto groupby() viene avanzato, il gruppo precedente non è più visibile. Quindi, se quei dati sono necessari in un secondo momento, dovrebbero essere archiviati come un elenco:
itertools.groupby() — Funzioni che creano iteratori per cicli efficienti — Documentazione Python 3.10.4

for k, g in itertools.groupby(l):
    print(k, g)
# 0 
# 1 
# 2 
# 0 

for k, g in itertools.groupby(l):
    print(k, list(g))
# 0 [0, 0, 0]
# 1 [1, 1]
# 2 [2]
# 0 [0, 0]

È possibile utilizzare la comprensione dell’elenco per ottenere un elenco di sole chiavi, solo gruppi o entrambi (tuple di chiave e gruppo).

print([k for k, g in itertools.groupby(l)])
# [0, 1, 2, 0]

print([list(g) for k, g in itertools.groupby(l)])
# [[0, 0, 0], [1, 1], [2], [0, 0]]

print([(k, list(g)) for k, g in itertools.groupby(l)])
# [(0, [0, 0, 0]), (1, [1, 1]), (2, [2]), (0, [0, 0])]

Specifica una funzione che calcola un valore chiave per ogni elemento:key

È possibile specificare il parametro chiave per itertools.groupby(). L’utilizzo della chiave è lo stesso di altre funzioni come sorted(), max(), min(), ecc.

In base al risultato della funzione (oggetto richiamabile) specificato in chiave, si determina se i valori degli elementi consecutivi sono gli stessi.

Ad esempio, se si specifica la funzione incorporata len(), che raggruppa la lunghezza (numero di caratteri) di una stringa, gli elementi con la stessa lunghezza vengonoti. Le parentesi () non sono necessarie quando si specifica la chiave.

l = ['aaa', 'bbb', 'ccc', 'a', 'b', 'aa', 'bb']
print([(k, list(g)) for k, g in itertools.groupby(l, len)])
# [(3, ['aaa', 'bbb', 'ccc']), (1, ['a', 'b']), (2, ['aa', 'bb'])]

Determina se il numero è pari o dispari con un’espressione lambda:

l = [0, 2, 0, 3, 1, 4, 4, 0]
print([(k, list(g)) for k, g in itertools.groupby(l, lambda x: x % 2)])
# [(0, [0, 2, 0]), (1, [3, 1]), (0, [4, 4, 0])]

Aggrega come GROUP BY in SQL

Puoi raggruppare dati bidimensionali (come un elenco di elenchi) in base a una determinata colonna, come GROUP BY in SQL, con chiave.

In questo caso, viene utilizzata un’espressione lambda per ottenere l’elemento nella posizione desiderata nell’elenco, ma è anche possibile utilizzare operator.itemgetter().

Inoltre, l’istruzione per viene utilizzato per semplificare la lettura dell’output, ma ovviamente puoi anche utilizzare la comprensione degli elenchi come negli esempi precedenti.

l = [[0, 'Alice', 0],
     [1, 'Alice', 10],
     [2, 'Bob', 20],
     [3, 'Bob', 30],
     [4, 'Alice', 40]]

for k, g in itertools.groupby(l, lambda x: x[1]):
    print(k, list(g))
# Alice [[0, 'Alice', 0], [1, 'Alice', 10]]
# Bob [[2, 'Bob', 20], [3, 'Bob', 30]]
# Alice [[4, 'Alice', 40]]

Con itertools.groupby() vengono raggruppati solo gli elementi consecutivi dello stesso valore. Per raggrupparli in()’ dall’ordine originale, ordina lelenco con sort.

Quando si ordina un elenco di elenchi, viene ordinato in elenco predefinito, l’elenco viene base al primo elemento di ogni elenco. Per ordinare in base all’elemento nella posizione data, specificare il parametro chiave di sorted().

for k, g in itertools.groupby(sorted(l, key=lambda x: x[1]), lambda x: x[1]):
    print(k, list(g))
# Alice [[0, 'Alice', 0], [1, 'Alice', 10], [4, 'Alice', 40]]
# Bob [[2, 'Bob', 20], [3, 'Bob', 30]]

Somma i numeri con un’espressione del generatore:

for k, g in itertools.groupby(sorted(l, key=lambda x: x[1]), lambda x: x[1]):
    print(k, sum(x[2] for x in g))
# Alice 50
# Bob 50

Nota che panda ha anche groupby() per il raggruppamento e l’aggregazione. Panda è più conveniente per la gestione dei dati complessi.

Per tupla e archi

Puoi usare itertools.groupby() per gestire elenchi non solo ma anche tuple, stringhe, ecc.

Per le tupla:

t = (0, 0, 0, 1, 1, 2, 0, 0)
print([(k, list(g)) for k, g in itertools.groupby(t)])
# [(0, [0, 0, 0]), (1, [1, 1]), (2, [2]), (0, [0, 0])]

Usa tuple() se vuoi trasformare un gruppo in una tupla invece che in una lista.

print(tuple((k, tuple(g)) for k, g in itertools.groupby(t)))
# ((0, (0, 0, 0)), (1, (1, 1)), (2, (2,)), (0, (0, 0)))

Per le stringhe:

s = 'aaabbcaa'
print([(k, list(g)) for k, g in itertools.groupby(s)])
# [('a', ['a', 'a', 'a']), ('b', ['b', 'b']), ('c', ['c']), ('a', ['a', 'a'])]

Usa join() se vuoi trasformare un gruppo in una stringa.

print([(k, ''.join(g)) for k, g in itertools.groupby(s)])
# [('a', 'aaa'), ('b', 'bb'), ('c', 'c'), ('a', 'aa')]

Naturalmente, puoi anche gestire qualsiasi altro oggetto iterabile con itertools.groupby().