Dict. aber Reihenfolge der Keys() wichtig :(

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.
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 15. November 2004, 22:16

Es ist schon das zweite mal, das ich eigentlich für ein paar Daten (vCard-Informationen) ein Dict nehmen würde... Nun ist es aber bekanntermaßen so, das die Keys() eines Dicts "durcheinander" gespeichert werden...

Ist ja normalerweise kein Problem, da es ja Daten sind die man über die Keys() ansprechen will...

Aber was mache ich, wenn die Reihenfolge doch wichtig ist?

Zwei Möglichkeiten hab ich mir Ausgedacht:
* Die Keys() beim "schreiben" des Dicts zusätzlich in einer Liste packen
* Kein Dict sondern eine Liste in einer Liste nehmen:
[ ["key1", "Wert1"] , ["key1", "Wert1"] ]

Gegen die erste Variante spricht eigentlich der "Speicherplatz", denn es werden gleiche Informationen zwei mal abgespeichert...
Ist die zweite Variante damit die beste??? Die zweite Variante erlaubt aber nicht das Typische ansprechen wie beim Dict über einen Key... (Wobei das bei meinem VCards-Problem egal ist)
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Montag 15. November 2004, 22:33

Hi Jens,

Zu Variante 2 (verschachtelte Listen; Listen mit Listen, Listen mit tuples, Listen mit dicts) habe ich selber schon gegriffen und Du kannst ja auch nach liste[0] sortieren.
Eine dritte Variante bietet Python2.4:

Code: Alles auswählen

>>> d = {1:'a',2:'b'}
>>> d = sorted(d.items())
Aber das ist wohl nicht unbedingt, was Du suchst.

Variante 1 ist wenig elegant, kann man aber ruhig nutzen - finde ich. Wenn Du nur eine Abfrage für ein "V-Card-Dict" machen möchtest mit einem Dutzend Einträgen: Warum nicht? Dann machst Du halt so was: l = [name, tel, ...]
und dann : for i in l: print dict oder so. Und l wäre dann eine "globale" Liste, die alle Funktionen kennen, die sie brauchen.

Gruß,
Christian
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 15. November 2004, 22:37

Ist es wirklich eine 2.4 neuheit, oder das selbe wie das:

Code: Alles auswählen

d = {1:'a',2:'b'}
k = d.keys()
k.sort()
print k
Also nur eine Alphabetisch sortierte Liste??? Darum dreht es sich bei mir nicht... Ich will die rheinfolge, mit der ich die Daten ins Dict geschrieben hab!
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Montag 15. November 2004, 22:46

Das ist mir schon klar, das Du nach was anderem suchtest. Aber dann mußt Du halt - nach meinem Wissen - ausweichen auf eine der anderen Alternativen.
sorted ist neu, version 2.3 kennt es nicht. Wenn nur eine sortierte Liste der Schlüssel herauskommt, wie in Deinem Beispiel, muß man halt über diese Liste die Abfrage im dict machen. Ist natürlich genauso gut - und genauso an Deiner Frage vorbei.

Ich dachte mir halt, daß ich das auch mal in die Runde werfe ...
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Montag 15. November 2004, 23:32

Hi jens,

ich würd das so machen:

Code: Alles auswählen

>>> mykeys = ["erster", "zweiter", "dritter", "vierter"]

>>> mydict = dict(zip(mykeys, [1,2,3,4]))

>>> print mydict
{'vierter': 4, 'dritter': 3, 'erster': 1, 'zweiter': 2}

>>> print keys[1], mydict[keys[1]]
zweiter 2
So hast Du die Schlüssel nur einmal definiert und hast ihre reihenfolge, ohne Redundanzen, da die Strings in den Schlüsseln des Dictionaries die gleichen (identische Instanzen) wie die Strings in der Liste sind.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 16. November 2004, 09:10

(in deinem Listing muß es mykeys und nicht nur keys heißen)

Ich hab deine Variante erst mal nicht verstanden, aber damit wurde mir es klar:

Code: Alles auswählen

mykeys = ["erster", "zweiter", "dritter", "vierter"]
myvalues = ["Wert1", "Wert2", "Wert3", "Wert4"]

mydict = dict(zip(mykeys, myvalues ))

print mydict.keys()[0]
print mykeys[3]

print id( mydict.keys()[0] )
print id( mykeys[3] )

for i in xrange( len(mydict) ):
    print mykeys[i], mydict[mykeys[i]]

Code: Alles auswählen

vierter
vierter
9221728
9221728
erster Wert1
zweiter Wert2
dritter Wert3
vierter Wert4
Nur, ob das jetzt einfacher als eine Liste in einer Liste ist, weiß ich noch nicht...
Treehorn
User
Beiträge: 2
Registriert: Montag 8. November 2004, 09:29

Dienstag 16. November 2004, 11:19

Speicher die Keys doch einfach von den Values getrennt in 2 Listen.
Zurgriff dann einfach so:

Code: Alles auswählen

keys = ["eins", "zwei", "drei", "vier", "fuenf", "sechs"]
vals = [1, 2, 3, 4, 5, 6]

beliebigeVariable = vals[keys.index("zwei")]
Wenn Du dir ne schöne Klasse draus machst und die entsprechenden Operatoren überschreibst sowie ne vernünftige Sammlung von Methoden zusammenstellst mit denen Du die "Paare" hinzufügen umstellen und dergleichen kannst, haste gleich was für die Zukunft.
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Dienstag 16. November 2004, 18:12

Hi. Gegenvorschlag: bau dir ne Klasse, die von dict abgeleitet und setz Dookies Variante um. Dann brauchen nur einige wenige Methoden überschrieben werden...
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 16. November 2004, 20:28

Milan hat geschrieben:Hi. Gegenvorschlag: bau dir ne Klasse, die von dict abgeleitet und setz Dookies Variante um. Dann brauchen nur einige wenige Methoden überschrieben werden...
Hmmm... Da weiß ich allerdings garnicht wo ich anfangen soll... Übersteigt wohl meine Kompetenzen :oops:
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Dienstag 16. November 2004, 21:09

Hi. Mal ein kleiner Versuch, etwas wiederverwendbares zu schaffen, denn das Konzept an sich geht für ein Script einfacher zu verwirklichen:

Code: Alles auswählen

class SortedDict(dict):
    __slots__=["__keylist"]
    def __init__(self,tuplelist=(),**kw):
        dict.__init__(self)
        self.__keylist=[]
        for k,v in tuplelist:
            self[k]=v
        self.update(kw)
    def __iter__(self):
        return iter(self.__keylist)
    def __delitem__(self,k):
        dict.__delitem__(self,k)
        self.__keylist.remove(k)
    def __setitem__(self,k,v):
        dict.__setitem__(self,k,v)
        if k in self.__keylist:
            self.__keylist.remove(k)
        self.__keylist.append(k)
    def clear(self):
        dict.clear(self)
        del self.__keylist[:]
    def copy(self):
        new=SortedDict()
        for k in self:
            new[k]=self[k]
        return new
    def items(self):
        return [(k,self[k]) for k in self]
    def iteritems(self):
        for k in self:
            yield (k,self[k])
    iterkeys=__iter__
    def itervalues(self):
        for k in self:
            yield self[k]
    def keys(self):
        return self.__keylist[:]
    def pop(self,k,d=None):
        v=dict.pop(k,d)
        try:
            self.__keylist.remove(k)
        except ValueError:
            pass
        return v
    def popitem(self):
        k,v=dict.popitem(self)
        try:
            self.__keylist.remove(k)
        except ValueError:
            pass
        return k,v
    def setdefault(self,k,d=None):
        erg=self.get(k,d)
        if k not in self:
            self[k]=d
        return erg
    def update(self,otherdict):
        for k,v in otherdict.iteritems():
            self[k]=v
    def values(self):
        return [self[k] for k in self]

    def fromkeys(self,S,v=None):
        new=SortedDict()
        for k in S:
            new[k]=v
        return new
Zuletzt geändert von Milan am Mittwoch 17. November 2004, 13:45, insgesamt 2-mal geändert.
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 16. November 2004, 21:31

Wow, was für'n Listing... Da verstehe ich erstmal nix... Aber mal Probieren:

Code: Alles auswählen

MySortedDict = SortedDict()

MySortedDict["Key1"]="Wert1"
MySortedDict["Key2"]="Wert2"

print MySortedDict
print MySortedDict.items()

for i in MySortedDict.keys():
    print i,"-",MySortedDict[i]

Code: Alles auswählen

{'Key2': 'Wert2', 'Key1': 'Wert1'}
[('Key1', 'Wert1'), ('Key2', 'Wert2')]
Key1 - Wert1
Key2 - Wert2
Nicht schlecht... Ist eine wirklich brauchbare Lösung...


Wobei das geht nicht so richtig:

Code: Alles auswählen

MySortedDict = SortedDict()

MySortedDict={ "Key0":"Wert0", "Key1":"Wert1" }
print MySortedDict

MySortedDict["Key2"]="Wert2"
MySortedDict["Key3"]="Wert3"
MySortedDict["Key4"]="Wert4"

for i in MySortedDict.keys():
    print i,"-",MySortedDict[i]

Code: Alles auswählen

{'Key1': 'Wert1', 'Key0': 'Wert0'}
Key3 - Wert3
Key2 - Wert2
Key1 - Wert1
Key0 - Wert0
Key4 - Wert4
Aber damit kann man leben...
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Dienstag 16. November 2004, 21:33

Hi. Hmmm, da muss ich mir noch aml die Init anschauen. Aber ansonsten mach doch sowas:

Code: Alles auswählen

MySortedDict = SortedDict()
MySortedDict.update({ "Key0":"Wert0", "Key1":"Wert1" })
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 16. November 2004, 21:38

Nur keine Mühe, mir reicht eigentlich schon das:

Code: Alles auswählen

class SortedDict(dict):

    __slots__=["__keylist"]

    def __init__(self,*args,**kw):
        dict.__init__(self,*args,**kw)
        self.__keylist=[]

    def __iter__(self):
        return iter(self.__keylist)

    def __setitem__(self,k,v):
        dict.__setitem__(self,k,v)
        if k in self.__keylist:
            self.__keylist.remove(k)
        self.__keylist.append(k)
        
    def keys(self):
        return self.__keylist[:]

Code: Alles auswählen

MySortedDict = SortedDict()

MySortedDict["Key1"]="Wert1"
MySortedDict["Key2"]="Wert2"
MySortedDict["Key3"]="Wert3"

for i in MySortedDict.keys():
    print i,"-",MySortedDict[i]


MySortedDict["Key2"]="Wert2XX"

MySortedDict["Key4"]="Wert4"
MySortedDict["Key5"]="Wert5"

print "="*15
for i in MySortedDict.keys():
    print i,"-",MySortedDict[i]

Code: Alles auswählen

Key1 - Wert1
Key2 - Wert2
Key3 - Wert3
===============
Key1 - Wert1
Key3 - Wert3
Key2 - Wert2XX
Key4 - Wert4
Key5 - Wert5
Hab nach und nach die Funktionen rauskommentiert und stets geprüft, ob das Ergebnis noch stimmt... Aber kann man es noch weiter zusammen kürzen???
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Dienstag 16. November 2004, 21:39

Verbessert, so müsste es gehen... wenn schon, denn schon. Soll ja was wiederverwendbares sein :wink:
Antworten