2009-10-10 2 views
5

Ich habe einige benutzerdefinierte Objekte und Wörterbücher, die ich sortieren möchte. Ich möchte beide Objekte die Wörterbücher zusammen sortieren. Ich möchte die Objekte nach einem Attribut und die Wörterbücher nach einem Schlüssel sortieren.Sortieren einer heterogenen Liste von Objekten in Python

object.name = 'Jack' 
d = {'name':'Jill'} 

sort_me =[object, d] 

Wie sortiere ich diese Liste mit dem Attribut name des Objekts und dem 'Name'-Schlüssel des Wörterbuchs?

Antwort

8

Was Sie sicherlich suchen, ist die Verwendung der Option key = für sorted(), die eine Funktion zur Verfügung stellt, die einen beliebigen Sortierschlüssel für jedes Element zurückgibt. Diese Funktion kann den Typ ihres Arguments prüfen und verschiedene Aktionen ausführen. Zum Beispiel:

import types 

class obj(object): 
    def __init__(self, arg): 
     self.name = arg 

def extract_name(obj): 
    if type(obj) is types.DictType: 
     return obj['name'] 
    else: 
     return obj.__dict__['name'] 

d = { 'name': 'Jill'}  
print sorted([obj('Jack'), d], key=extract_name) 

Weitere Informationen finden Sie auf der Python wiki

RichieHindle Vorschlag der Verwendung von isinstance ist gut zu finden. Und während ich es war dachte ich, es wäre schön, beliebige Elementnamen zu unterstützen, anstatt zu ‚namen‘:

def extract_elem_v2(elem_name): 
    def key_extractor(obj): 
     dct = obj if isinstance(obj, dict) else obj.__dict__ 
     return dct[elem_name] 
    return key_extractor 

, die Sie mögen so verwenden können:

print sorted(list_of_stuff, key=extract_elem_v2('name')) 
+3

+1. Kleiner Vorschlag: 'isinstance (obj, dict)' wäre ordentlicher und würde Klassen erlauben, die von 'dict' abgeleitet sind. – RichieHindle

+0

Sie haben Recht, Insinance ist eine bessere Wahl, nicht sicher, warum ich nicht daran gedacht habe. Aktualisierte Version an die Antwort angehängt. Vielen Dank! –

+0

Vielen Dank Jack! Diese Antwort ist wunderschön. – hekevintran

2
sort_me.sort(key=attr_or_itemgetter('name')) 

Wo attr_or_itemgetter() :

class attr_or_itemgetter(object): 
    def __init__(self, name): 
     self.name = name 
    def __call__(self, obj): 
     try: return getattr(obj, name) 
     except AttributeError: 
      return obj[name] 

Hinweis: es absichtlich überprüft nicht für Wörterbuchtyp, daher attr_or_itemgetter('items') angewendet auf ein Wörterbuch wird dict.items Methode zurückgeben.

+1

Ich finde diese Antwort mehr Pythonic als die basierend auf Typ-Prüfung (kann ein wenig langsamer sein, wenn es viele dicts in der Sequenz sortiert wird, aber alles was es braucht, um es zu optimieren diese Verwendung ist das Umdrehen, was ist der Versuch Körper und was ist der Körper außer, und das Abfangen verschiedener Ausnahmen; -0). –

1

Das funktionierte für mich. Beachten Sie, dass sort() die sortierte Liste nicht zurückgibt, aber sorted(), wenn Sie dies an eine Vorlage weitergeben möchten, sollten Sie in den Parametern sorted oder sort verwenden, bevor Sie die Liste als Parameter übergeben.

itemized_action_list = list(chain(detection_point.insertbodyaction_set.all(), 
            detection_point.insertheaderaction_set.all(), 
            detection_point.modifybodyaction_set.all(), 
            detection_point.modifyheaderaction_set.all(), 
            detection_point.removebodyaction_set.all(), 
            detection_point.removeheaderaction_set.all(), 
            detection_point.redirectaction_set.all())) 

sorted(itemized_action_list, key=attrgetter('priority')) 
+0

Willkommen bei SO. Versuchen Sie, in Ihren Beispielen klar und präzise zu sein. Ohne weitere Informationen ist es nicht möglich zu sagen, was Ihre Liste enthält. – joaquin