Seite 1 von 1

Sortierung von Listen (Tupel-Listen) anhand einer Liste

Verfasst: Dienstag 13. Juli 2010, 11:09
von rads
Hallo,

da es sich wohl um ein leichteres Problem handelt, mach ich es kurz.

Code: Alles auswählen

dicFull = {'field4':10,'field2':20,'field1':30,'field3':40}
    partList = ['field4','field3']
Ich möchte partList anhand der value-Werte aus dem Dict dicFull sortieren.

Wie mache ich das in einer eleganten Version?

Schonmal vielen Dank

Grüße Stefan

Re: Sortierung

Verfasst: Dienstag 13. Juli 2010, 11:34
von BlackJack

Code: Alles auswählen

part_list.sort(key=dic_full.__getitem__)

Re: Sortierung

Verfasst: Dienstag 13. Juli 2010, 12:21
von rads
Super vielen Dank BlackJack.

Re: Sortierung

Verfasst: Dienstag 13. Juli 2010, 13:34
von rads
Noch eine Frage,

angenommen in part_list gibt es Einträge die in dic_full nicht auftreten, dann würde er momentan eine Key-Not Found exception werfen.
Ist es möglich diese Werte "zu ignorieren" wobei ich meine das sich "einfach" am Ende unsortiert verbleiben?

Oder würde das nur über den Weg gehen, nicht im dict vorhandene Werte aus der liste entfernen und nachträglich wieder hinzufügen?

Grüße

Beispiel:

Code: Alles auswählen

dicFull = {'field4':40,'field2':20,'field1':30,'field3':10}
    partList = ['field2','field4','field3','field5']
    partList.sort(key=dicFull.__getitem__)
    print partList

Traceback (most recent call last):
  File "....py", line 13, in <module>
    partList.sort(key=dicFull.__getitem__)
KeyError: 'field5'

Re: Sortierung

Verfasst: Dienstag 13. Juli 2010, 13:40
von Trichter
Das könnte man vielleicht mit einem defaultdict machen, das standardmäßig einen sehr großen Wert liefert, wenn der Eintrag nicht vorhanden ist.

Re: Sortierung

Verfasst: Dienstag 13. Juli 2010, 13:52
von rads
Im moment mache ich es halt wie folgt (Testimplementierung)

Code: Alles auswählen

 dicFull = {'field4':40,'field2':20,'field1':30,'field3':10}
    partList = ['field2','field4','field3','field5']
    tmpList = []
    for part in partList:
        if not dicFull.has_key(part):
            partList.remove(part)
            tmpList.append(part)
    partList.sort(key=dicFull.__getitem__)
    partList = partList + tmpList
    print partList
Sicherlich nicht die idealiste Liste, aber so wie ich den sort - Befehl verstehe gibts ja keine Möglichkeit für einen skipl.

Re: Sortierung

Verfasst: Dienstag 13. Juli 2010, 13:58
von EyDu
Manchmal hilft es auch ungemein nicht einfach nur Code blind zu übernehmen, sondern auch in die Dokumentation zu schauen was sort noch für mögliche Argumente hat.

Re: Sortierung

Verfasst: Dienstag 13. Juli 2010, 14:20
von BlackJack
@rads: Du könntest auch einfach eine Funktion schreiben die dafür sorgt, dass für Elemente die nicht in dem Dictionary vorkommen, grundsätzlich ein höherer Wert zurückgegeben wird, als bei denen die Werte im Dictionary haben. Beispiel:

Code: Alles auswählen

    dic_full = {'field4': 40, 'field2': 20, 'field1': 30, 'field3': 10}
    parts = ['field2', 'field4', 'field3', 'field5']
    
    def key_func(item):
        try:
            return (0, dic_full[item])
        except KeyError:
            return (1, None)
    
    parts.sort(key=key_func)
    print parts
Ansonsten solltest Du `list.remove()` so nicht in einer Schleife verwenden. Das wäre nicht nur ineffizient, sondern funktioniert auch nicht richtig. Wenn Du Elemente aus einer Liste entfernst, über die Du gerade iterierst, dann rutschen ja alle Folge-Elemente einen Platz nach vorne. Davon bekommt aber die Schleife nichts mit und es werden Elemente ungeprüft übersprungen.

Re: Sortierung

Verfasst: Dienstag 13. Juli 2010, 14:43
von rads
@BlackJack Nochmals vielen Dank.

Ich habe es jetzt über list comprehension gemacht, fande ich dann eine zumindest optisch schön schlanke Lösung.

Code: Alles auswählen

    dicFull = {'field4':40,'field2':20,'field1':30,'field3':10}
    partList = ['field2','field4','field3','field5']
    tmpList = [  x for x in partList if x not in dicFull.keys()]
    partList = [ x for x in partList if x not in tmpList]
    partList.sort( key=dicFull.__getitem__)
    partList = partList + tmpList
    print partList
ist ja an sich dann nicht mehr ganz so schrecklich?

Re: Sortierung

Verfasst: Dienstag 13. Juli 2010, 15:36
von BlackJack
Immer noch schrecklich. In der ersten "list comprehension" (LC) wird für jedes Element in der Liste eine Liste mit den Schlüsseln des Dictionaries erzeugt und in dem linear gesucht und in der zweiten LC werden Elemente linear in der Liste von der ersten LC gesucht. Effizient ist das nicht gerade.

Edit: So wird die `parts`-Liste nur einmal durchlaufen und auch effizient im Dictionary gesucht:

Code: Alles auswählen

    dic_full = {'field4': 40, 'field2': 20, 'field1': 30, 'field3': 10}
    parts = ['field2', 'field4', 'field3', 'field5']
    
    sortable_items = list()
    remaining_items = list()
    for item in parts:
        (sortable_items if item in dic_full else remaining_items).append(item)
    sortable_items.sort(key=dic_full.__getitem__)
    parts = sortable_items + remaining_items
    print parts

Sortierung einer Tupe-Liste anhand einer Referenz-Liste

Verfasst: Mittwoch 14. Juli 2010, 08:18
von rads
Danke für die Anregungen BlackJack. Wurde berücksichtigt.

Anbei eine Variation und weil mich die Lösung von BlackJack interessiert hat.

Sortierung einer Tupe-Liste anhand einer Referenz-Liste wobei auch nicht alle
Werte in der Referenzliste vorhanden sein müssen

Falls es wer mal brauchen kann bzw. so wie ich nicht auf anhieb drauf kommt.

Code: Alles auswählen

orderList = ['nr4', 'nr2', 'nr3', 'nr1']
    sqlMap = [('nr1', u'0'), ('nr5', u'blubb'), ('nr3', 25)]
    
    def key_func(item):
        try:
            return (0, orderList.index(item[0]))
        except Exception:
            return (1, None)
        
   
    sqlMap.sort(key=key_func)

    print sqlMap
Grüße Stefan

Re: Sortierung von Listen (Tupel-Listen) anhand einer Liste

Verfasst: Mittwoch 14. Juli 2010, 12:31
von mkesper

Code: Alles auswählen

except Exception
ist eine schreckliche Idee!

Re: Sortierung von Listen (Tupel-Listen) anhand einer Liste

Verfasst: Mittwoch 14. Juli 2010, 12:38
von Barabbas
Ich habe gehört, man spricht in diesem Fall auch von "Pokeman-Exceptions" ("Catch 'em all!") :wink:

Re: Sortierung von Listen (Tupel-Listen) anhand einer Liste

Verfasst: Donnerstag 15. Juli 2010, 12:25
von cofi
mkesper hat geschrieben:

Code: Alles auswählen

except Exception
ist eine schreckliche Idee!
Na immerhin besser als ein blankes `except`.
@rads: Warum die Faulheit? `ValueError` ist nicht sonderlich laenger.

Re: Sortierung von Listen (Tupel-Listen) anhand einer Liste

Verfasst: Donnerstag 15. Juli 2010, 13:42
von rads
@cofi

naja ich bin javaverwöhnt in kombination von eclipse, da ist die Refactoringfunktionaliät, naja sagen wir mal ausgeprägter, als bei Pydev.
An sich liegt es daran, das er bei der automatischen generierung des try:except: Blockes Exception schreibt,und nicht die
eigentlich möglichen auftretenden Exceptions. Ka wo ich das einstellen kann, aber ja es ist wohl schlichte Faulheit.

Re: Sortierung von Listen (Tupel-Listen) anhand einer Liste

Verfasst: Donnerstag 15. Juli 2010, 15:40
von Leonidas
rads hat geschrieben:Ka wo ich das einstellen kann, aber ja es ist wohl schlichte Faulheit.
Nein, das lässt sich nicht statisch ermitteln. Jedenfalls ist das so keine gute Einstellung.