Antworten:
Wenn dies der OrderedDict()
Fall ist, können Sie einfach auf die Elemente zugreifen, indem Sie sie indizieren, indem Sie die Tupel von (Schlüssel-, Wert-) Paaren wie folgt abrufen
>>> import collections
>>> d = collections.OrderedDict()
>>> d['foo'] = 'python'
>>> d['bar'] = 'spam'
>>> d.items()
[('foo', 'python'), ('bar', 'spam')]
>>> d.items()[0]
('foo', 'python')
>>> d.items()[1]
('bar', 'spam')
Hinweis für Python 3.X.
dict.items
würde ein iterierbares Diktatansichtsobjekt anstelle einer Liste zurückgeben. Wir müssen den Aufruf in eine Liste einschließen, um die Indizierung zu ermöglichen
>>> items = list(d.items())
>>> items
[('foo', 'python'), ('bar', 'spam')]
>>> items[0]
('foo', 'python')
>>> items[1]
('bar', 'spam')
list(d.items())
list(d.items())
indem Sie verwenden next(islice(d.items(), 1))
, um('bar', 'spam')
Müssen Sie ein OrderedDict verwenden oder möchten Sie speziell einen kartenähnlichen Typ, der in irgendeiner Weise mit schneller Positionsindizierung geordnet ist? Wenn letzteres der Fall ist, betrachten Sie einen der vielen sortierten Diktattypen von Python (der Schlüssel-Wert-Paare basierend auf der Sortierreihenfolge der Schlüssel sortiert). Einige Implementierungen unterstützen auch die schnelle Indizierung. Zu diesem Zweck verfügt das sortedcontainers- Projekt beispielsweise über einen SortedDict- Typ.
>>> from sortedcontainers import SortedDict
>>> sd = SortedDict()
>>> sd['foo'] = 'python'
>>> sd['bar'] = 'spam'
>>> print sd.iloc[0] # Note that 'bar' comes before 'foo' in sort order.
'bar'
>>> # If you want the value, then simple do a key lookup:
>>> print sd[sd.iloc[1]]
'python'
SortedDict
eine Schlüsselfunktion verwenden, um Vergleiche zu vermeiden. Wie : SortedDict(lambda key: 0, ...)
. Die Schlüssel werden dann unsortiert, bleiben jedoch in einer stabilen Reihenfolge und sind indizierbar.
Hier ist ein Sonderfall, wenn Sie den ersten Eintrag (oder einen ähnlichen Eintrag) in einem OrderedDict wünschen, ohne eine Liste zu erstellen. (Dies wurde auf Python 3 aktualisiert):
>>> from collections import OrderedDict
>>>
>>> d = OrderedDict()
>>> d["foo"] = "one"
>>> d["bar"] = "two"
>>> d["baz"] = "three"
>>> next(iter(d.items()))
('foo', 'one')
>>> next(iter(d.values()))
'one'
(Wenn Sie zum ersten Mal "next ()" sagen, bedeutet dies wirklich "first".)
In meinem informellen Test ist next(iter(d.items()))
mit einem kleinen OrderedDict nur ein kleines bisschen schneller als items()[0]
. Mit einem OrderedDict von 10.000 Einträgen next(iter(d.items()))
war das etwa 200-mal schneller als items()[0]
.
ABER wenn Sie die Liste items () einmal speichern und die Liste dann häufig verwenden, kann dies schneller sein. Oder wenn Sie wiederholt {einen items () - Iterator erstellen und ihn an die gewünschte Position bringen}, kann dies langsamer sein.
OrderedDict
s haben keine iteritems()
Methode, daher müssen Sie Folgendes tun, um das erste Element zu erhalten : next(iter(d.items()))
.
d.items()
scheint es kein Iterator zu sein, also hilft der Iter vor nicht? Es wird immer noch die vollständige Liste zurückgegeben :(
odict_iterator
und wurde mir im IRC #python bestätigt, dass dies keine Kopie der Liste erstellt.
Die Verwendung von IndexedOrderedDict aus dem indexed
Paket ist erheblich effizienter .
Nach Niklas 'Kommentar habe ich einen Benchmark für OrderedDict und IndexedOrderedDict mit 1000 Einträgen durchgeführt.
In [1]: from numpy import *
In [2]: from indexed import IndexedOrderedDict
In [3]: id=IndexedOrderedDict(zip(arange(1000),random.random(1000)))
In [4]: timeit id.keys()[56]
1000000 loops, best of 3: 969 ns per loop
In [8]: from collections import OrderedDict
In [9]: od=OrderedDict(zip(arange(1000),random.random(1000)))
In [10]: timeit od.keys()[56]
10000 loops, best of 3: 104 µs per loop
IndexedOrderedDict ist in diesem speziellen Fall ~ 100-mal schneller bei der Indizierung von Elementen an einer bestimmten Position.
indexed.py
stattdessen zu installieren indexed
.
Dieses Community-Wiki versucht, vorhandene Antworten zu sammeln.
Python 2.7
In Python 2, das keys()
, values()
und items()
Funktionen der OrderedDict
Rückkehr Listen. Am values
einfachsten ist es am Beispiel
d.values()[0] # "python"
d.values()[1] # "spam"
Für große Sammlungen , wo man nur über einen einzigen Index kümmern, können Sie vermeiden , um die vollständige Liste der Erstellung der Generator - Versionen verwenden, iterkeys
, itervalues
und iteritems
:
import itertools
next(itertools.islice(d.itervalues(), 0, 1)) # "python"
next(itertools.islice(d.itervalues(), 1, 2)) # "spam"
Das Paket indexed.py bietet IndexedOrderedDict
, das für diesen Anwendungsfall entwickelt wurde und die schnellste Option ist.
from indexed import IndexedOrderedDict
d = IndexedOrderedDict({'foo':'python','bar':'spam'})
d.values()[0] # "python"
d.values()[1] # "spam"
Die Verwendung von itervalues kann für große Wörterbücher mit wahlfreiem Zugriff erheblich schneller sein:
$ python2 -m timeit -s 'from collections import OrderedDict; from random import randint; size = 1000; d = OrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); d.values()[i:i+1]'
1000 loops, best of 3: 259 usec per loop
$ python2 -m timeit -s 'from collections import OrderedDict; from random import randint; size = 10000; d = OrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); d.values()[i:i+1]'
100 loops, best of 3: 2.3 msec per loop
$ python2 -m timeit -s 'from collections import OrderedDict; from random import randint; size = 100000; d = OrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); d.values()[i:i+1]'
10 loops, best of 3: 24.5 msec per loop
$ python2 -m timeit -s 'from collections import OrderedDict; from random import randint; size = 1000; d = OrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); next(itertools.islice(d.itervalues(), i, i+1))'
10000 loops, best of 3: 118 usec per loop
$ python2 -m timeit -s 'from collections import OrderedDict; from random import randint; size = 10000; d = OrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); next(itertools.islice(d.itervalues(), i, i+1))'
1000 loops, best of 3: 1.26 msec per loop
$ python2 -m timeit -s 'from collections import OrderedDict; from random import randint; size = 100000; d = OrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); next(itertools.islice(d.itervalues(), i, i+1))'
100 loops, best of 3: 10.9 msec per loop
$ python2 -m timeit -s 'from indexed import IndexedOrderedDict; from random import randint; size = 1000; d = IndexedOrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); d.values()[i]'
100000 loops, best of 3: 2.19 usec per loop
$ python2 -m timeit -s 'from indexed import IndexedOrderedDict; from random import randint; size = 10000; d = IndexedOrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); d.values()[i]'
100000 loops, best of 3: 2.24 usec per loop
$ python2 -m timeit -s 'from indexed import IndexedOrderedDict; from random import randint; size = 100000; d = IndexedOrderedDict({i:i for i in range(size)})' 'i = randint(0, size-1); d.values()[i]'
100000 loops, best of 3: 2.61 usec per loop
+--------+-----------+----------------+---------+
| size | list (ms) | generator (ms) | indexed |
+--------+-----------+----------------+---------+
| 1000 | .259 | .118 | .00219 |
| 10000 | 2.3 | 1.26 | .00224 |
| 100000 | 24.5 | 10.9 | .00261 |
+--------+-----------+----------------+---------+
Python 3.6
Python 3 hat die gleichen zwei grundlegenden Optionen (Liste gegen Generator), aber die dict-Methoden geben standardmäßig Generatoren zurück.
Listenmethode:
list(d.values())[0] # "python"
list(d.values())[1] # "spam"
Generatormethode:
import itertools
next(itertools.islice(d.values(), 0, 1)) # "python"
next(itertools.islice(d.values(), 1, 2)) # "spam"
Python 3-Wörterbücher sind um eine Größenordnung schneller als Python 2 und haben ähnliche Beschleunigungen für die Verwendung von Generatoren.
+--------+-----------+----------------+---------+
| size | list (ms) | generator (ms) | indexed |
+--------+-----------+----------------+---------+
| 1000 | .0316 | .0165 | .00262 |
| 10000 | .288 | .166 | .00294 |
| 100000 | 3.53 | 1.48 | .00332 |
+--------+-----------+----------------+---------+
Es ist eine neue Ära und mit Python 3.6.1 behalten Wörterbücher jetzt ihre Reihenfolge bei. Diese Semantik ist nicht explizit, da dies eine BDFL-Genehmigung erfordern würde. Aber Raymond Hettinger ist das nächstbeste (und witzigere) und er macht ein ziemlich starkes Argument dafür, dass Wörterbücher für eine sehr lange Zeit bestellt werden.
So ist es jetzt einfach, Slices eines Wörterbuchs zu erstellen:
test_dict = {
'first': 1,
'second': 2,
'third': 3,
'fourth': 4
}
list(test_dict.items())[:2]
Hinweis: Die Beibehaltung der diktonaren Einfügereihenfolge ist jetzt in Python 3.7 offiziell .
Für OrderedDict () können Sie auf die Elemente zugreifen, indem Sie sie indizieren, indem Sie die Tupel von (Schlüssel-, Wert-) Paaren wie folgt abrufen oder '.values ()' verwenden.
>>> import collections
>>> d = collections.OrderedDict()
>>> d['foo'] = 'python'
>>> d['bar'] = 'spam'
>>> d.items()
[('foo', 'python'), ('bar', 'spam')]
>>>d.values()
odict_values(['python','spam'])
>>>list(d.values())
['python','spam']
items
Methode in 3.x ein interaktives Wörterbuchansichtsobjekt anstelle einer Liste zurückgibt und kein Slicing oder Indizieren unterstützt. Sie müssten es also zuerst in eine Liste umwandeln. docs.python.org/3.3/library/stdtypes.html#dict-views