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: 18260
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: 14019
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.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Benutzeravatar
__blackjack__
User
Beiträge: 14019
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()
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
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: 14019
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.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

@__blackjack__: Danke.
Antworten