Ohne zusätzliche eckige Klammern keine Tupel bei `Counter()`

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Hallo

Der Container Datentyp `Counter` verhält sich beim Hinzufügen von Tupeln mit der Methode `update()` anders als Listen mit der Methode `append()`. Im folgenden Code bedarf es bei `counter2` zusätzliche eckige Klammern um die Tupel, damit die Ausgabe identisch zur Liste `data` ist.

Weshalb benötigt es beim `Counter` zusätzliche eckige Klammern, damit die Tupel auch so erhalten bleiben?

Code: Alles auswählen

from collections import Counter
from random import randint

counter1 = Counter()
counter2= Counter()
data = []


for i in range(100):
    first = (randint(0, 1000))
    second = (randint(0, 1000))
    counter1.update((first, second))  # Tupel bleiben nicht erhalten
    counter2.update([(first, second)])  # Tupel bleiben erhalten
    data.append((first, second))

print("counter1:", sorted(counter1))
print("counter2:", sorted(counter2))
print("data:", sorted(data))
Gruß
Atalanttore
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

update erwartet mehrere Elemente, das Äquivalent bei Listen wäre extend.
Daher erst die Liste erzeugen und dann den Counter:

Code: Alles auswählen

from collections import Counter
from random import randint

data = []
for i in range(100):
    first = randint(0, 1000)
    second = randint(0, 1000)
    data.append((first, second))
    
counter = Counter(data)
print("counter:", sorted(counter))
print("data:", sorted(data))

Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

@Sirius3: Danke für die Erklärung.

Erst die Daten erzeugen und dann den `Counter` wird im konkreten Anwendungsfall nicht funktionieren. Es fallen laufend neue Werte an und die Werte mit den meisten Vorkommen sollen zuerst bearbeitet werden.
Benutzeravatar
__blackjack__
User
Beiträge: 13117
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Atalanttore: Dann benutze halt nicht die `update()`-Methode sondern addiere manuell 1. Wobei Du dann eigentlich auch den `Counter` nicht wirklich brauchst, sofern Du davon nicht noch was anderes brauchst was ein `collections.defaultdict` nicht auch bietet.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13117
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Code: Alles auswählen

#!/usr/bin/env python3
from collections import defaultdict
from random import randint


def main():
    histogram = defaultdict(int)
    pairs = []

    for _ in range(100):
        pair = (randint(0, 1000), randint(0, 1000))
        histogram[pair] += 1
        pairs.append(pair)

    print("histogram:", sorted(histogram))
    print("pairs:", sorted(pairs))


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

@__blackjack__: Aus dem `Counter` benutze ich noch die Methode `most_common()` zum Bestimmen der aktuell häufigsten Elemente.
Benutzeravatar
__blackjack__
User
Beiträge: 13117
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Atalanttore: Ah, okay. Die Lösung bleibt dann aber fast die gleiche, nur eben mit dem `Counter`-Objekt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

@__blackjack__: Danke.
Antworten