Listen nach mehreren Vorgaben sortieren

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
Bennhardt
User
Beiträge: 15
Registriert: Donnerstag 9. Februar 2006, 14:21
Wohnort: Buchholz in der Nordheide

Freitag 10. Februar 2006, 15:57

Hallo,

ich hatte schon in diversen Cookbooks geschaut und auch hier gesucht.
Ich muss Listen in einer Liste nach 2 Suchkriterien sortieren.
Das sieht etwas so aus:

[["Bob","34 Jahre","183 cm","45 kg"],["Bob","67 Jahre","209 cm","120 kg"],["Charly","23 Jahre","172","56 kg"]] usw.

Das Problem: Nach dem ersten Index soll immer sortiert werden (also "Bob","Bob","Charly" etc.), jedoch soll per Variable mitgegeben werden, nach welchem Index ich als nächstes sortiere also nach Alter, Größe, Gewicht.
Man soll am Ende eine Liste bekommen, in der alle Leute nach Namen sortiert sind, aber eben variabel (wie ich das löse ist schon klar) nach Gewicht ODER Größe ODER Alter.

Ich hab das schon versucht:


Code: Alles auswählen

a = [["Bob","34 Jahre","183 cm","45 kg"],["Bob","67 Jahre","209 cm","120 kg"],["Charly","23 Jahre","172","56 kg"]]
def compare(a,b):
    return cmp(a[1],b[1])
a.sort(compare)

print a
Hier kann ich wenigstens schon mal aussuchen, nach welchem Index ich sortieren möchte. Das nütz mir aber nix, weil ich eben nur nach EINEM index sortieren kann.
Ich hatte mir schon überlegt, für jeden Namen eine eigene Liste zu erstellen, aber das ist nicht variabel genug.
Wie kann man da rangehen?
helmut
User
Beiträge: 57
Registriert: Mittwoch 2. November 2005, 07:45
Wohnort: Dormagen

Freitag 10. Februar 2006, 16:34

Hallo,

ich befuerchte meine Loesung ist nicht sehr "pythonisch"; es scheint aber zu klappen.

Code: Alles auswählen

a = [["Bob","94 Jahre","183 cm","45 kg"],["Bob","67 Jahre","209 cm","120 kg"],["Charly","23 Jahre","172","56 kg"]]
inx2=1
def compare(a,b):
    if a[0]<b[0]:
        return -1
    elif a[0]==b[0]:
        return cmp(a[inx2],b[inx2])
    else:
        return 1
    
a.sort(compare)
print a 
#[['Bob', '67 Jahre', '209 cm', '120 kg'], ['Bob', '94 Jahre', '183 cm', '45 kg'], ['Charly', '23 Jahre', '172', '56 kg']]
Helmut
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Freitag 10. Februar 2006, 17:12

Hi!

Ich vereinfache das mal, und nehme Alter, Grösse, ... als Zahlen.

Code: Alles auswählen

 l = [["Bob", 34, 183, 45],["Sepp", 67, 209, 120], ["Alice", 23, 172, 56],["Bob", 77, 20, 11]]
n = [((x[0],x[1]),x) for x in l]
n.sort()
print [i[1] for i in n]
Ich erstelle also eine List n. Diese hat als Element immer ein Tupel mit den Grössen nach denen sortiert werden soll (also hier Name und Alter) und den ursprünglichen Listeneintrag selbst. n wird dann sortiert, vorrangig nach den Elementen in den Tupel. Dann printe ich die zweiten Elemente der sortierten Liste, und das sind ja die ursprünglichen Einträge.
Ich hoffe ich hab richtig gedacht ;)

Gruß, mawe
Bennhardt
User
Beiträge: 15
Registriert: Donnerstag 9. Februar 2006, 14:21
Wohnort: Buchholz in der Nordheide

Freitag 10. Februar 2006, 19:01

Klasse! Teste ich, sobald ich wieder im Büro bin! Jetzt hab ich erstmal FREIZEIT :D

Danke schonmal im Voraus!!

Schönes WE wünscht,
Ben
BlackJack

Samstag 11. Februar 2006, 00:25

Helmuts Lösung etwas pythonischer:

Code: Alles auswählen

persons = [["Bob","94 Jahre","183 cm","45 kg"],
           ["Bob","67 Jahre","209 cm","120 kg"],
           ["Charly","23 Jahre","172","56 kg"]]

def make_compare(second_index):
    def compare(a, b):
        return cmp(a[0], b[0]) or cmp(a[second_index], b[second_index])
    return compare

persons.sort(make_compare(1))
print persons
woolfy
User
Beiträge: 19
Registriert: Montag 6. Februar 2006, 15:14
Wohnort: Stuttgart

Sonntag 12. Februar 2006, 02:01

Hier noch eine aufgebohrte Variante, die gerade in meinem Zustand geistiger Umnachtung entstanden ist.

Damit kann man Daten nach x-beliebig vielen Kriterien sortieren und das jeweils auf- bzw. absteigend.
Das könnte man nun noch mit getattr() auf eine Liste von Objekten abändern, um nach deren Eigenschaften sortieren zu können.

Performance hab ich mir noch nicht angesehen und das mit dem eval kanns noch nicht sein. Vielleicht hat jemand noch ein paar Ideen...

Code: Alles auswählen

data = [
    [1,'a','x'],
    [1,'a','y'],
    [1,'a','z'],
    [1,'b','x'],
    [1,'b','y'],
    [1,'b','z'],
    [1,'c','x'],
    [1,'c','y'],
    [1,'c','z'],
    [2,'a','x'],
    [2,'a','y'],
    [2,'a','z'],
    [2,'b','x'],
    [2,'b','y'],
    [2,'b','z'],
    [2,'c','x'],
    [2,'c','y'],
    [2,'c','z'],
    [3,'a','x'],
    [3,'a','y'],
    [3,'a','z'],
    [3,'b','x'],
    [3,'b','y'],
    [3,'b','z'],
    [3,'c','x'],
    [3,'c','y'],
    [3,'c','z'],
]

def comp(sort_criteria):
    def helper(a,b):
        return eval(" or ".join([(order=='asc' and str(cmp(a[criteria],b[criteria])) or str(cmp(b[criteria],a[criteria]))) for criteria, order in sort_criteria]))
    return helper

criteria = ((1,'asc'),(2,'desc'),(0,'asc'))
data.sort(comp(criteria))
for x in data:
    print x
LG
Jens
Bennhardt
User
Beiträge: 15
Registriert: Donnerstag 9. Februar 2006, 14:21
Wohnort: Buchholz in der Nordheide

Montag 13. Februar 2006, 09:02

Ja super! Genau das, was ich brauche!
Performance ist nicht so ausschlaggebend, da die Liste, die ich zu sortieren habe nicht allzu groß ist.
Antworten