722 Stimmen

Eine Liste nach mehreren Attributen sortieren?

Ich habe eine Liste von Listen:

[[12, 'tall', 'blue', 1],
[2, 'short', 'red', 9],
[4, 'tall', 'blue', 13]]

Wenn ich nach einem Element sortieren wollte, z. B. nach dem Element "groß/klein", könnte ich dies über s = sorted(s, key = itemgetter(1)) .

Wenn ich sortieren wollte nach beide groß/kurz und Farbe, könnte ich die Sortierung zweimal durchführen, einmal für jedes Element, aber gibt es einen schnelleren Weg?

1235voto

Mark Byers Punkte 761508

Ein Schlüssel kann eine Funktion sein, die ein Tupel zurückgibt:

s = sorted(s, key = lambda x: (x[1], x[2]))

Das Gleiche können Sie auch erreichen, indem Sie itemgetter (das ist schneller und vermeidet einen Python-Funktionsaufruf):

import operator
s = sorted(s, key = operator.itemgetter(1, 2))

Und beachten Sie, dass Sie hier die Option sort statt mit sorted und dann neu zugewiesen werden:

s.sort(key = operator.itemgetter(1, 2))

58voto

Clint Blatchford Punkte 531

Ich bin nicht sicher, ob das die pythonischste Methode ist ... Ich hatte eine Liste von Tupeln, die 1. nach absteigenden ganzzahligen Werten und 2. alphabetisch sortiert werden musste. Dies erforderte eine Umkehrung der ganzzahligen Sortierung, aber nicht der alphabetischen Sortierung. Hier war meine Lösung: (spontan in einer Prüfung, ich wusste nicht einmal, dass man sortierte Funktionen "verschachteln" kann)

a = [('Al', 2),('Bill', 1),('Carol', 2), ('Abel', 3), ('Zeke', 2), ('Chris', 1)]  
b = sorted(sorted(a, key = lambda x : x[0]), key = lambda x : x[1], reverse = True)  
print(b)  
[('Abel', 3), ('Al', 2), ('Carol', 2), ('Zeke', 2), ('Bill', 1), ('Chris', 1)]

26voto

ron_g Punkte 1176

Einige Jahre zu spät zur Party, aber ich möchte beide nach 2 Kriterien sortieren und verwenden. reverse=True . Falls jemand anderes wissen möchte, wie das geht, können Sie Ihre Kriterien (Funktionen) in Klammern einschließen:

s = sorted(my_list, key=lambda i: ( criteria_1(i), criteria_2(i) ), reverse=True)

7voto

UpAndAdam Punkte 4290

Es scheint, als könnten Sie eine list anstelle einer tuple . Dies wird meines Erachtens wichtiger, wenn Sie Attribute anstelle von "magischen Indizes" einer Liste/eines Tupels abrufen.

In meinem Fall wollte ich nach mehreren Attributen einer Klasse sortieren, wobei die eingehenden Schlüssel Zeichenketten waren. Ich brauchte verschiedene Sortierungen an verschiedenen Stellen und wollte eine gemeinsame Standardsortierung für die übergeordnete Klasse, mit der die Clients interagieren. Ich musste die "Sortierschlüssel" nur überschreiben, wenn ich es wirklich "brauchte", aber auch so, dass ich sie als Listen speichern konnte, die die Klasse gemeinsam nutzen konnte

Also habe ich zunächst eine Hilfsmethode definiert

def attr_sort(self, attrs=['someAttributeString']:
  '''helper to sort by the attributes named by strings of attrs in order'''
  return lambda k: [ getattr(k, attr) for attr in attrs ]

dann zu verwenden

# would defined elsewhere but showing here for consiseness
self.SortListA = ['attrA', 'attrB']
self.SortListB = ['attrC', 'attrA']
records = .... #list of my objects to sort
records.sort(key=self.attr_sort(attrs=self.SortListA))
# perhaps later nearby or in another function
more_records = .... #another list
more_records.sort(key=self.attr_sort(attrs=self.SortListB))

Dabei wird die generierte Lambda-Funktion verwendet, um die Liste nach object.attrA und dann object.attrB unter der Annahme, dass object hat einen Getter, der den angegebenen Stringnamen entspricht. Und der zweite Fall würde sortieren nach object.attrC puis object.attrA .

Dies ermöglicht es Ihnen auch, potenziell nach außen Sortierung Entscheidungen zu teilen gleich von einem Verbraucher, ein Unit-Test, oder für sie vielleicht sagen, wie sie wollen, dass die Sortierung für einige Betrieb in Ihrem api durch nur haben, um Ihnen eine Liste und nicht Kopplung sie zu Ihrem Back-End-Implementierung getan.

7voto

Golden Lion Punkte 2590

Die Liste der Liste in eine Liste von Tupeln umwandeln und dann die Tupel nach mehreren Feldern sortieren.

 data=[[12, 'tall', 'blue', 1],[2, 'short', 'red', 9],[4, 'tall', 'blue', 13]]

 data=[tuple(x) for x in data]
 result = sorted(data, key = lambda x: (x[1], x[2]))
 print(result)

Ausgabe:

 [(2, 'short', 'red', 9), (12, 'tall', 'blue', 1), (4, 'tall', 'blue', 13)]

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X