Liste ausdünnen

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
snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

Guten Abend zusammen,

ich habe folgende Liste und möchte die Liste insoweit ausdünnen, dass gleiche "Unterlisten" zusammengefasst werden.

Code: Alles auswählen

liste = [[1, 'SIM20', 'BBU-IM', '2Hj'], [1, 'SIM18', 'BBU-IM', '02uW'], [1, 'SIM18', 'BBU-IM', '02uW'], [2, 'SIM18', 'BBU-IM', None]]
Aus folgenden beiden "Unterlisten" wird dann nur noch eine "Unterliste":

Code: Alles auswählen

[1, 'SIM18', 'BBU-IM', '02uW'], [1, 'SIM18', 'BBU-IM', '02uW']
zusammengefasst

Code: Alles auswählen

 [2, 'SIM18', 'BBU-IM', '02uW']
Die ausgedünnte Liste sollte dann als Ergebnis so aussehen:

Code: Alles auswählen

liste = [[1, 'SIM20', 'BBU-IM', '2Hj'], [2, 'SIM18', 'BBU-IM', '02uW'], [2, 'SIM18', 'BBU-IM', None]]
Die Wertigkeit von 1 und 1 wurde mit 2 angegeben (addiert).

Die Liste beinhaltet viel mehr Unterlisten, die ich hier der Einfachkeithalber nicht dargestellt habe. Kann mir jemand weiterhelfen? Ich finde keinen Anfang.

Viele Grüße
snowflake
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

Es gibt da vermutlich mehrere Lösungen. Meine funktioniert mit Dictionaries. Die Schlüssel von Dictionaries sind einmalig und (in neueren Python-Versionen) auch nach der Eingabereihenfolge sortiert. Wenn du deine inneren Listen (in Tupel konvertiert) als Schlüssel nimmst, kannst du dir die Zahl, die bei Wiederholungen aufsummiert werden soll, als Wert merken (die setdefault Methode von Dictionaries ist dafür hilfreich). Aus dem Dictionary kannst du dir dann deine Liste wieder zusammenbauen.

Ergebnis:

Code: Alles auswählen

In [1]: items = [[1, 'SIM20', 'BBU-IM', '2Hj'], [1, 'SIM18', 'BBU-IM', '02uW'], [1, 'SIM18', 'BBU-IM', '02uW'], [2, 'SIM18', 'BBU-IM', None]]                 

...                                                                            

In [5]: new_items                                                                                                                                             
Out[5]: 
[[1, 'SIM20', 'BBU-IM', '2Hj'],
 [2, 'SIM18', 'BBU-IM', '02uW'],
 [2, 'SIM18', 'BBU-IM', None]]
Caskuda
User
Beiträge: 26
Registriert: Sonntag 15. März 2020, 22:09

Mit dem Counter - Dictionary:

Code: Alles auswählen

from collections import Counter 

liste = [[1, 'SIM20', 'BBU-IM', '2Hj'], [1, 'SIM18', 'BBU-IM', '02uW'], [1, 'SIM18', 'BBU-IM', '02uW'], [2, 'SIM18', 'BBU-IM', None]]
#print(liste)

myCount = Counter()
for item in liste:
    n, *vals = item
    vals = tuple(vals)
    myCount[vals] += n

#print(myCount)

liste = [[myCount.get(vals)] + list(vals) for vals in myCount]

print(liste)
snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

Guten Morgen Caskuda,

vielen Dank für Deinen Lösungsvorschlag (danke auch an nezzcarth). Auf diesen Ansatz wäre ich im Leben nicht gekommen. Er funktioniert hervorragend.
Was ich aber nicht verstehe ist folgende Stelle:

Code: Alles auswählen

n, *vals = item
Warum wird hier die Anzahl an n und der Rest an *vals übergeben?

Nochmals vielen Dank.

snowflake
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

snowflake
User
Beiträge: 93
Registriert: Mittwoch 9. November 2016, 15:46

Ok, vielen Dank. Mit dem Link ist es jetzt klar.
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

Hier meine Lösung mit setdefault:

Code: Alles auswählen

In [1]: items = [[1, 'SIM20', 'BBU-IM', '2Hj'], [1, 'SIM18', 'BBU-IM', '02uW'], [1, 'SIM18', 'BBU-IM', '02uW'], [2, 'SIM18', 'BBU-IM', None]]                 

In [2]: result = dict()                                                                                                                                       

In [3]: for item in items: 
   ...:     item = tuple(item) 
   ...:     result.setdefault(item, 0) 
   ...:     result[item] += item[0] 
   ...:                                                                                                                                                       

In [4]: new_items = [[value, *key[1:]] for key, value in result.items()]                                                                                      

In [5]: new_items                                                                                                                                             
Out[5]: 
[[1, 'SIM20', 'BBU-IM', '2Hj'],
 [2, 'SIM18', 'BBU-IM', '02uW'],
 [2, 'SIM18', 'BBU-IM', None]]
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Von Counter wird fast nichts benutzt und setdefault kann man auch eleganter per defaultdict lösen. Variablennamen werden komplett klein geschrieben. Sie bestehen nicht aus Abkürzungen oder sinnfreien Präfixen wie my.

Code: Alles auswählen

from collections import defaultdict

liste = [[1, 'SIM20', 'BBU-IM', '2Hj'], [1, 'SIM18', 'BBU-IM', '02uW'], [1, 'SIM18', 'BBU-IM', '02uW'], [2, 'SIM18', 'BBU-IM', None]]

counted_whatever = defaultdict(int)
for count, *whatever in liste:
    counted_whatever[tuple(whatever)] += count
liste = [[count] + list(whatever) for count, whatever in counted_whatever.items()]
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Anregung für die letzte Zeile (ungetestet):

Code: Alles auswählen

liste = [[count, *whatever] for count, whatever in counted_whatever.items()]
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

Sirius3 hat geschrieben: Samstag 11. Juli 2020, 09:56 … setdefault kann man auch eleganter per defaultdict lösen.
Interessant, dass du das sagst. Ich habe früher immer defaultdict für so etwas verwendet, in neuem Code nehme ich aber nach Möglichkeit setdefault und refactore teilweise auch älteren Code in der Hinsicht. Aus meiner Sicht macht defaultdict mitunter mehr Probleme, als es löst (zum Beispiel dadurch, dass jeder Schlüsselzugriff gleich einen Schlüssel erzeugt). Hier ist das evtl. nicht so relevant.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Das sind ja meist unterschiedliche Anwendungsfälle. Wörterbücher, auf die man mit konkreten Schlüsseln zugreift, und solchen, die zum Sammeln von unbekannten Daten da sind. Im ersten Fall würde ich normalerweise auch kein defaultdict benutzen.
Antworten