[Python-de] geordnetes dict

Thomas 'PointedEars' Lahn PointedEars at web.de
So Apr 21 18:11:49 CEST 2013


Philipp Kraus wrote:

> ich habe jetzt 2 Tage an einem Fehler gehangen, weil ich selbst nicht
> an die passende Datenstruktur gedacht habe:
> 
> Ich habe ein dict in der Form:
> 
> x = {
>     "first" : {.....},
>     "second" : {....},
>    "aaa" : {....},
> }
> 
> so ist es jedenfalls im Quellcode definiert, ich iteriere nun über das
> dict, aber ich muss die Reihenfolge beibehalten (ich hatte daran nicht
> gedacht). Die Reihenfolge muss exakt so sein, wie im Code angegeben
> also first, second, aaa, real ist sie aber aaa, first, second und das
> führt bei mir zu einem Fehler.
> 
> Ich hatte gesehen, dass es Komponenten wie z.B. das StableDict gibt.
> Meine Frage ist aber, ob man so etwas auch ohne zusätzliche Komponenten
> realisieren kann. Mein erster Gedanke war, dies so zu machen:
> 
> x = [
>    { "first" : {...} },
>    { "second" : {...} ),
>    { "aaa" : {...} }
> ]
> 
> aber damit habe ich nicht mehr die Eindeutigkeit der Einträge gegeben.
> Was gibt es für Möglichkeiten ab Python 2.6 dieses Problem sinnvoll zu
> lösen?

OrderedDict kannte ich bisher nicht, und zusätzliche Komponenten (dazu zählt 
für mich auch ein Backport) wolltest Du nicht, deshalb hätte ich das Problem 
im Prinzip so wie Du gelöst.  Allerdings mit einer eigenen Klasse, die 
verhindert, dass Duplikate entstehen können, und sowohl die dict-artige 
Zugriffe als auch dict-artige Iteration erlaubt:

class MyOrderedDict (dict):
    """A dictionary that observes addition order"""

    def __init__ (self, _list=None):
        self.from_list(_list)

    def __getitem__ (self, key):
        return self._items[self._key_to_index[key]]['value']

    def __setitem__ (self, key, value):
        index = self._key_to_index.get(key, None)

        if index is None:
            self._items.append({'key': key, 'value': value})
            index = len(self._items) - 1
            self._key_to_index[key] = index
        else:
            self._items[index]['value'] = value

        return self._items[index]['value']

    def __iter__ (self):
        return self

    def _reset_iter_index (self):
        self._iter_index = 0

    def next (self):
        if self._iter_index >= len(self._items):
            self._reset_iter_index()
            raise StopIteration

        item = self._items[self._iter_index]
        self._iter_index = self._iter_index + 1
        return item['key']

    def iteritems (self):
        result = []
        for item in self._items:
            result.append((item['key'], item['value']))
        return result

    def items (self):
        """Compatibility method, iteritems() is preferred"""
        return self.iteritems()

    def clear (self):
        self._items = []
        self._key_to_index = {}
        self._reset_iter_index()

    def from_list (self, _list):
        self.clear()
        if _list is not None:
            for item in _list:
                self[item[0]] = item[1]

d = MyOrderedDict([
        ['first', {'answer': 23}],
        ['second', 2],
        ['aaa', True]
    ])
d["first"] = {'answer': 42}
d["aa"] = False

# test
for key, value in d.iteritems():
    print key, value

# ----

(Ob das Ableiten von dict eine gute Idee ist, weiss ich nicht; vermutlich 
müsste man dafür noch mehr dict-Methoden überschreiben.)

Das hatte sich für mich heute relativ schnell aus

<http://docs.python.org/2.6/tutorial/classes.html#iterators>
und
<http://docs.python.org/2.6/reference/datamodel.html#object.__iter__>

ergeben.  Etwas mit Python 2.6 unter PyDev getestet, funktioniert 
anscheinend.


Apropos: PyDev hat finanzielle Probleme; eine kleine Spende wäre hilfreich, 
damit es weiterentwickelt werden kann.  Hab' länger kein Python mehr (damit) 
programmiert, und bin durch diesen Thread darauf aufmerksam geworden.

<http://igg.me/p/pydev-and-liclipse-for-a-fast-sexy-and-dark-
eclipse/x/3069022>

-- 
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.


Mehr Informationen über die Mailingliste python-de