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:

Dienstag 16. November 2004, 21:40

Ahhh Halt... Ich sehe gerade, das die veränderung eines Wertes die Reihenfolge durcheinander bring :(

Code: Alles auswählen

MySortedDict["Key2"]="Wert2XX"
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Dienstag 16. November 2004, 21:45

Hi. Ja, das hab ich mir so gedacht. Ansonsten musst du halt __setitem__ verändern, dass der wert nicht gelöscht wird, falls vorhanden (und dann aber auch nicht noch hinzugefügt wird).
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 16. November 2004, 21:49

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
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Dienstag 16. November 2004, 22:20

Hi jens,

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,
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]#!/usr/bin/env python
import this[/code]
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Mittwoch 17. November 2004, 13:48

Hi. Nett, aber nicht ganz in Ordnung:

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
Kann man außerdem nicht das superobj als attribut speichern? Sonst muss es ja jedesmal erzeugt werden...
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Mittwoch 17. November 2004, 14:03

Hi,

uups stimmt, hab halt nich alles getestet, is aber nur ne Abfrage nötig beim __repr__ und __str__:

Code: Alles auswählen

    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
nö super könnte man schlecht in einem Attribut speichern, dann könnte man von Lict keine Klassen mehr ableiten da ja super dann für diese abgeleiteten Klassen nicht mehr stimmen würde! Besser die Metaklasse für autosuper aus dem Beispiel auf der Pythonhomepagedokumentation zu Newstyleklassen verwenden.


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:

Freitag 19. November 2004, 23:48

Mit __delitem__ scheint auch was nicht zu stimmen:

Code: Alles auswählen

  File "SortedDict.py", line 132, in ?
    del( MySortedDict["Key2"] )
  File "SortedDict.py", line 49, in __delitem__
    super(Lict, self).__delitem(key)
AttributeError: 'super' object has no attribute '_Lict__delitem'
Wie geht es außerdem einen Wert an einer bestimmten Stelle hinzuzufügen?

Code: Alles auswählen

    MyLict["Key1"]="Wert1"
    MyLict["Key2"]="Wert2"
    MyLict["Key3"]="Wert3"
Also Beispielsweise zwischen Key2 und Key3, soll MyLict["Key2b"]="Wert2b" rein...

Vielleicht ist es für mich persönlich doch einfach zwei Listen zu verwalten...
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Samstag 20. November 2004, 12:56

Hi,

Da fehlen 2 "_" :)

Code: Alles auswählen

    def __delitem__(self, key):
        if type(key) is Index:
            key = self.__keylist[key]
        super(Lict, self).__delitem__(key)
        del self.__keylist[key]
Das Einfügen an einem Bestimmten Index ginge so:

Code: Alles auswählen

    def insert(self, index, key, value):
        self.__keylist.insert(index, key)
        super(Lict, self)[key] = value
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:

Samstag 20. November 2004, 19:52

Dookie hat geschrieben:Da fehlen 2 "_" :)
das ist es nicht ganz:

Code: Alles auswählen

    def __delitem__(self, key):
        if type(key) is Index:
            key = self.__keylist[key]
        super(Lict, self).__delitem__(key)
        del self.__keylist[ self.__keylist.index(key) ]
(Die letzte Zeile ist anders)

Code: Alles auswählen

    MyLict.insert(2, "Key2", "Wert2")
Geht leider nicht:

Code: Alles auswählen

Traceback (most recent call last):
  File "SortedDict.py", line 138, in ?
    MyLict.insert(2, "Key2", "Wert2")
  File "SortedDict.py", line 54, in insert
    super(Lict, self)[key] = value
TypeError: object does not support item assignment
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Samstag 20. November 2004, 20:16

Code: Alles auswählen

    def insert(self, index, key, value):
        self.__keylist.insert(index, key)
        super(Lict, self).__setitem__(key, value)
so getestet und läuft :)


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:

Samstag 20. November 2004, 21:33

Jup! Jetzt geht's...

Damit man nicht den ganzen Thread durchlesen muß, hier nochmal die aktuelle Version, mit allen Verbesserungen:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
    Modul:          Lict
    Description:    Mix of list and dict
    Version:        0.1.1
    Copyright:      2004 by Fritz Cizmarov fritz@sol.at
    Created:        16. Nov. 2004
    Last modified:  20. 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[ self.__keylist.index(key) ]

    def insert(self, index, key, value):
        self.__keylist.insert(index, key)
        super(Lict, self).__setitem__(key, value)

    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()






if __name__=="__main__":
    print "->",__file__,"<- SelbstTest\n"

    def LictAusgeben():
        print "="*40
        for k,v in MyLict.iteritems():
            print k,"-",v
        print "="*40

    MyLict = Lict()

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

    LictAusgeben()

    MyLict["Key2"]="Wert2XX"

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

    LictAusgeben()

    del( MyLict["Key2"] )

    LictAusgeben()

    MyLict.insert(2, "Key2", "Wert2NEU")

    LictAusgeben()
Antworten