Dict. aber Reihenfolge der Keys() wichtig :(
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
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)
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)
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:
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
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())
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
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Ist es wirklich eine 2.4 neuheit, oder das selbe wie das:
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!
Code: Alles auswählen
d = {1:'a',2:'b'}
k = d.keys()
k.sort()
print k
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 ...
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 ...
-
- Python-Forum Veteran
- Beiträge: 2010
- Registriert: Freitag 11. Oktober 2002, 18:00
- Wohnort: Salzburg
- Kontaktdaten:
Hi jens,
ich würd das so machen:
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
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
Gruß
Dookie
[code]#!/usr/bin/env python
import this[/code]
import this[/code]
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
(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:
Nur, ob das jetzt einfacher als eine Liste in einer Liste ist, weiß ich noch nicht...
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
Speicher die Keys doch einfach von den Values getrennt in 2 Listen.
Zurgriff dann einfach so:
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.
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")]
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Hmmm... Da weiß ich allerdings garnicht wo ich anfangen soll... Übersteigt wohl meine KompetenzenMilan 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...

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.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Wow, was für'n Listing... Da verstehe ich erstmal nix... Aber mal Probieren:
Nicht schlecht... Ist eine wirklich brauchbare Lösung...
Wobei das geht nicht so richtig:
Aber damit kann man leben...
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
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
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" })
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Nur keine Mühe, mir reicht eigentlich schon das:
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???
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
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Ahhh Halt... Ich sehe gerade, das die veränderung eines Wertes die Reihenfolge durcheinander bring 

Code: Alles auswählen
MySortedDict["Key2"]="Wert2XX"
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Thx.... So geht's:
Code: Alles auswählen
class SortedDict(dict):
__slots__=["__keylist"]
def __init__(self,*args,**kw):
dict.__init__(self)
self.__keylist=[]
def __iter__(self):
return iter(self.__keylist)
def __setitem__(self,k,v):
dict.__setitem__(self,k,v)
if not k in self.__keylist:
self.__keylist.append(k)
def keys(self):
return self.__keylist[:]
Code: Alles auswählen
Key1 - Wert1
Key2 - Wert2
Key3 - Wert3
===============
Key1 - Wert1
Key2 - Wert2XX
Key3 - Wert3
Key4 - Wert4
Key5 - Wert5
-
- Python-Forum Veteran
- Beiträge: 2010
- Registriert: Freitag 11. Oktober 2002, 18:00
- Wohnort: Salzburg
- Kontaktdaten:
Hi jens,
Hab auch mal was gebastelt. Index ist eine Hilfsklasse um auch über den Index auf die Einträge im Dictionary zugreifen zu können.
Gruß
Dookie
Edit by Milan: Änderungen von Dookie zwecks Übersichtlichkeit eingefügt
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
Modul: Lict
Description: Mix of list and dict
Version: 0.1
Copyright: 2004 by Fritz Cizmarov fritz@sol.at
Created: 16. Nov. 2004
Last modified: 16. Nov. 2004
License: free
Requirements: Python2.3
Exports: Classes and Functions to export
"""
class Index(int):
""" Helperclass for access Lict by Index """
__slots__ = []
class Lict(dict):
__slots__ = ["__keylist"]
def __init__(self, *args, **kw):
super(Lict, self).__init__(*args, **kw)
self.__keylist = []
if len(args) == 1 and isinstance(args[0], (tuple, list)):
for key, value in args[0]:
self.__keylist.append(key)
for key in kw:
self.__keylist.append(key)
def __getitem__(self, key):
if type(key) is Index:
key = self.__keylist[key]
return super(Lict, self).__getitem__(key)
def __setitem__(self, key, value):
""" sets item, if item not exists append it """
if type(key) is Index:
key = self.__keylist[key]
elif key not in self.__keylist:
self.__keylist.append(key)
super(Lict, self).__setitem__(key, value)
def __delitem__(self, key):
if type(key) is Index:
key = self.__keylist[key]
super(Lict, self).__delitem__(key)
del self.__keylist[key]
def __str__(self):
tpl = "{"+("%s : %s, "*len(self.__keylist))[:-2]+"}"
if self.__keylist:
data = [repr(x) for x in reduce(lambda a, b: a+b, self.iteritems())]
return tpl % tuple(data)
else:
return tpl
def __repr__(self):
tpl = "Lict(["+("(%s, %s), "*len(self.__keylist))[:-2]+"])"
if self.__keylist:
data = [repr(x) for x in reduce(lambda a, b: a+b, self.iteritems())]
return tpl % tuple(data)
else:
return tpl
def __iter__(self):
return iter(self.__keylist)
def iteritems(self):
for key in self.__keylist:
yield key, self[key]
iterkeys = __iter__
def itervalues(self):
for key in self.__keylist:
yield self[key]
def update(self, E):
if not isinstance(E, Lict):
raise TypeError("E is not from type Lict!")
for key in E:
self[key] = E[key]
def pop(self, key=None):
if key is None:
key = self.__keylist[-1]
elif type(key) is Index:
key = self.__keylist[key]
self.keylist.remove(key)
return super(Lict, self).pop(key)
def reverse(self):
self.__keylist.reverse()
def sort(self):
self.__keylist.sort()
def insert(self, index, key, value):
self.__keylist.insert(index, key)
super(Lict, self).__setitem__(key, value)
if __name__ == "__main__":
a = Lict((('a', "eins"),('b', "zwei"), ('c', "drei")))
print a
a[Index(1)]="neu"
print a
a["d"] = "ganzneu"
print a
for i in xrange(len(a)):
print a[Index(i)],
for i in a:
print i,
Gruß
Dookie
Edit by Milan: Änderungen von Dookie zwecks Übersichtlichkeit eingefügt
[code]#!/usr/bin/env python
import this[/code]
import this[/code]
Hi. Nett, aber nicht ganz in Ordnung:
Kann man außerdem nicht das superobj als attribut speichern? Sonst muss es ja jedesmal erzeugt werden...
Code: Alles auswählen
>>> Lict()
Traceback (most recent call last):
File "<pyshell#9>", line 1, in -toplevel-
Lict()
File "<pyshell#1>", line 40, in __repr__
data = [repr(x) for x in reduce(lambda a, b: a+b, self.iteritems())]
TypeError: reduce() of empty sequence with no initial value
>>> Lict({"a":"b"})
Traceback (most recent call last):
File "<pyshell#10>", line 1, in -toplevel-
Lict({"a":"b"})
File "<pyshell#1>", line 40, in __repr__
data = [repr(x) for x in reduce(lambda a, b: a+b, self.iteritems())]
TypeError: reduce() of empty sequence with no initial value