2016-02-28 17 views
5

Ich habe ein Objekt, das eine Liste von Listen von Wörterbüchern ist:Sortieren einer Liste von Listen der Wörterbücher in Python

myObject =[[{ "play": 5.00, "id": 1, "uid": "abc" }, \ 
      { "play": 1.00, "id": 2, "uid": "def" }], \ 
      [{ "play": 6.00, "id": 3, "uid": "ghi" }, \ 
      { "play": 7.00, "id": 4, "uid": "jkl" }], \ 
      [{ "play": 3.00, "id": 5, "uid": "mno" }, \ 
      { "play": 1.00, "id": 6, "uid": "pqr" }]] 

Ich möchte durch die Summe der play Werte in den Wörterbüchern jeder verschachtelt die Liste sortieren Liste. Das Objekt würde dann wie folgt sortiert werden:

myObject =[[{ "play": 6.00, "id": 3, "uid": "ghi" }, \ 
      { "play": 7.00, "id": 4, "uid": "jkl" }], \ 
      [{ "play": 5.00, "id": 1, "uid": "abc" }, \ 
      { "play": 1.00, "id": 2, "uid": "def" }], \ 
      [{ "play": 3.00, "id": 5, "uid": "mno" }, \ 
      { "play": 1.00, "id": 6, "uid": "pqr" }]] 

Wenn es nur eine Liste von dicts war dann:

sorted(myObject, key=sum(map(itemgetter(play))), reverse=True)

funktionieren würde. Ich kann nicht herausfinden, wie das geht, ohne die Liste zu überfliegen, die Summe zu berechnen und dann zu sortieren. Genau das mache ich jetzt, aber ich versuche, die Effizienz dieses Codes durch das Entfernen von Schleifen zu erhöhen, weil meine Liste 100 Millionen von Listen enthält.

+2

Nur als eine Anmerkung: Sie brauchen die abschließenden '' '' Zeilenfortsetzungen in diesem Fall nicht. Da die Zeilen mit einem Komma enden und die Listen-Literale immer noch "offen" sind, erwartet Python automatisch, dass die nächste Zeile dort weiterläuft. – poke

Antwort

4

Ihre Idee ist schon sehr gut, eine benutzerdefinierte Schlüsselfunktion zu verwenden, wenn das Sortieren und mit sum, map und ein itemgetter auf den play Schlüsseln:

key=sum(map(itemgetter(play))) 

Sie können ein Problem gibt aber: Das key Argument erwartet eine Funktion, die ein Element Ihrer Liste übernimmt, die Sie sortieren. Aber weder sum noch map geben eine Funktion zurück, so dass Sie sie nicht als Schlüsselfunktion verwenden können. Stattdessen könnten Sie eine Lambda-Funktion erstellen, die diese Kombination für jedes Element ausführt. Die anderen Probleme sind, dass play stattdessen eine Zeichenfolge 'play' sein sollte, und dass map die Unterliste als Argument nehmen sollte. So Ihre Schlüsselfunktion würde wie folgt aussehen:

key=lambda x: sum(map(itemgetter('play'), x)) 

Diese btw ist. funktional äquivalente Verständnis der folgenden Generator, der besser lesbar sein könnte:

key=lambda x: sum(y['play'] for y in x) 

Mit diesem mit sorted sollte funktionieren, aber Sie sollten stattdessen direkt mit list.sort Sortierung der Liste prüfen.

>>> myObject = [[{ "play": 5.00, "id": 1, "uid": "abc" }, 
       { "play": 1.00, "id": 2, "uid": "def" }], 
       [{ "play": 6.00, "id": 3, "uid": "ghi" }, 
       { "play": 7.00, "id": 4, "uid": "jkl" }], 
       [{ "play": 3.00, "id": 5, "uid": "mno" }, 
       { "play": 1.00, "id": 6, "uid": "pqr" }]] 

>>> myObject.sort(key=lambda x: sum(y['play'] for y in x), reverse=True) 

>>> for x in myObject: 
     print(x) 

[{'play': 6.0, 'uid': 'ghi', 'id': 3}, {'play': 7.0, 'uid': 'jkl', 'id': 4}] 
[{'play': 5.0, 'uid': 'abc', 'id': 1}, {'play': 1.0, 'uid': 'def', 'id': 2}] 
[{'play': 3.0, 'uid': 'mno', 'id': 5}, {'play': 1.0, 'uid': 'pqr', 'id': 6}] 

(Btw myObject ist Art von einem schlechten Namen für eine Liste von Dingen.)


Soweit die Effizienz oder die Komplexität Ihres Problems geht, Sie können wirklich nicht vermeiden, jede Unterliste irgendwann durchlaufen zu müssen. Es ist unmöglich, die Summe dieser Werte zu bestimmen, ohne die Werte zu betrachten, so offensichtlich können Sie das unmöglich vermeiden.

Sie sollten jedoch sicherstellen, dass jede Summe nur einmal berechnet wird, um zu vermeiden, dass Sie die Elemente in den Unterlisten mehr als einmal ansehen müssen. Zum Glück, das Sortieren der Standard list.sort verwenden, funktioniert aber genau das garantieren:

Der Schlüssel für jedes Element in der Liste entspricht, einmal berechnet und dann für den gesamten Sortierprozess verwendet.

So haben Sie eine sehr effiziente Lösung für dieses Sortierproblem.

+0

Sollte es nicht "reverse = True" sein, um am höchsten zu werden –

+0

@PaulRooney Oh ja, ich habe dieses Detail in der Frage verpasst (obwohl es für das Sortierproblem nicht wirklich relevant ist). Vielen Dank! – poke

Verwandte Themen