Seite 1 von 1

Liste ausdünnen

Verfasst: Freitag 10. Juli 2020, 19:08
von snowflake
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

Re: Liste ausdünnen

Verfasst: Freitag 10. Juli 2020, 19:59
von nezzcarth
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]]

Re: Liste ausdünnen

Verfasst: Samstag 11. Juli 2020, 00:00
von Caskuda
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)

Re: Liste ausdünnen

Verfasst: Samstag 11. Juli 2020, 07:13
von snowflake
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

Re: Liste ausdünnen

Verfasst: Samstag 11. Juli 2020, 07:45
von __deets__

Re: Liste ausdünnen

Verfasst: Samstag 11. Juli 2020, 08:05
von snowflake
Ok, vielen Dank. Mit dem Link ist es jetzt klar.

Re: Liste ausdünnen

Verfasst: Samstag 11. Juli 2020, 08:41
von nezzcarth
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]]

Re: Liste ausdünnen

Verfasst: Samstag 11. Juli 2020, 09:56
von Sirius3
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()]

Re: Liste ausdünnen

Verfasst: Samstag 11. Juli 2020, 10:00
von __blackjack__
Anregung für die letzte Zeile (ungetestet):

Code: Alles auswählen

liste = [[count, *whatever] for count, whatever in counted_whatever.items()]

Re: Liste ausdünnen

Verfasst: Samstag 11. Juli 2020, 10:39
von nezzcarth
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.

Re: Liste ausdünnen

Verfasst: Samstag 11. Juli 2020, 13:54
von Sirius3
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.