Dictionary mit Listen als values nach größtem Wert suchen

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
EmaNymton
User
Beiträge: 174
Registriert: Sonntag 30. Mai 2010, 14:07

Hallo,
folgendes dictionary sei gegeben:

Code: Alles auswählen

d={'a':[1,2,3],'b':[5,4,6],'c':[3,7,4]}
Ich möchte jetzt den key abfragen, wo der größte Wert aller Zahlen in der Liste vorkommt. Das bekomme ich soweit hin:

Code: Alles auswählen

>>> max(d.iteritems(),key=lambda x: max(x[1]))
('c', [3, 7, 4])
Das Problem, dass ich habe ist, dass in meinem Dictionary auch durchaus leere Listen als value vorkommen können.
Da ist max natürlich nicht drauf anzuwenden.

Wie kann man das in die lambda-Funktion einbauen?

Ist wahrscheinlich ganz einfach, jedoch hab ich mal wieder ein Brett vor dem Kopf :(
lunar

Filtere leere Listen doch einfach vorher raus:

Code: Alles auswählen

items = (item for item in d.iteritems() if item[1])
max(items, key=lambda item: max(item[1]))
EmaNymton
User
Beiträge: 174
Registriert: Sonntag 30. Mai 2010, 14:07

Hmm, stimmt, darauf bin ich nicht gekommen, ich sag ja Brett vor dem Kopf. :D
Hab mir jetzt noch was anderes zusammengebastelt, kann man das auch so machen?

Code: Alles auswählen

max(d.iteritems(),key=lambda x: max(x[1]) if len(x[1])>0 else None)
lunar

Ich weiß nicht, würde aber pauschal nein sagen. Damit das funktioniert, muss "None" sich mit Zahlen vergleichen lassen, und noch dazu immer kleiner sein als jede beliebige Zahl. Ich weiß nicht auswendig, ob dieses Verhalten von der Dokumentation garantiert ist, mir persönlich ist es in jedem Fall zu viel Magie.
BlackJack

@EmaNymton: Ich würde es auch einfach etwas ausführlicher schreiben statt alles in einen möglichst magischen Ausdruck zu quetschen.

Edit: Blödsinn entfernt. Ich bekomme halt manchmal Probleme wenn da so magische Indizes wie 1 verwendet werden. :-)

Edit2: Deshalb würde ich für das hier plädieren:

Code: Alles auswählen

max(((k, v) for k, v in d.iteritems() if v), key=lambda (k, v): max(v))
Benutzeravatar
snafu
User
Beiträge: 6881
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

lunar hat geschrieben:Ich weiß nicht, würde aber pauschal nein sagen. Damit das funktioniert, muss "None" sich mit Zahlen vergleichen lassen, und noch dazu immer kleiner sein als jede beliebige Zahl. Ich weiß nicht auswendig, ob dieses Verhalten von der Dokumentation garantiert ist, mir persönlich ist es in jedem Fall zu viel Magie.
Zumindest fällt man damit in Python 3.x auf die Nase:

Code: Alles auswählen

Python 2.6.4 (r264:75706, Dec  7 2009, 18:45:15) 
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> None < 0
True

Code: Alles auswählen

Python 3.1.1+ (r311:74480, Nov  2 2009, 14:49:22) 
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> None < 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: NoneType() < int()
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

BlackJack hat geschrieben: Edit2: Deshalb würde ich für das hier plädieren:

Code: Alles auswählen

max(((k, v) for k, v in d.iteritems() if v), key=lambda (k, v): max(v))
Das lambda geht so mit Python 3.x nicht mehr, da bleibt dann doch nur die magische 1. Oder geht es irgendwie eleganter?
BlackJack

@bords0: Kommt auf die Definition von "elegant" an. Man könnte auch einfach eine Funktion mit ``def`` erstellen und dort als erstes das Argument auf zwei Namen entpacken.

`k` und `v` sind hier im übrigen auch nur Namen/Kürzel weil ich nicht weiss wofür die eigentlich stehen sollen -- in einem echten Programm würde ich versuchen die aussagekräftiger zu gestalten.
Benutzeravatar
pillmuncher
User
Beiträge: 1531
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Wie wär's hiermit?

Code: Alles auswählen

>>> max((max(v), k, v) for k, v in d.iteritems() if v)[1:]
('c', [3, 7, 4])
In specifications, Murphy's Law supersedes Ohm's.
Antworten