Jawaban:
Jika OrderedDict()
Anda dapat dengan mudah mengakses elemen dengan mengindeks dengan mendapatkan tupel pasangan (kunci, nilai) sebagai berikut
>>> 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')
Catatan untuk Python 3.X
dict.items
akan mengembalikan objek tampilan dict yang dapat diubah daripada daftar. Kita perlu memasukkan panggilan ke daftar untuk memungkinkan pengindeksan
>>> items = list(d.items())
>>> items
[('foo', 'python'), ('bar', 'spam')]
>>> items[0]
('foo', 'python')
>>> items[1]
('bar', 'spam')
list(d.items())
list(d.items())
dengan menggunakan next(islice(d.items(), 1))
untuk mendapatkan('bar', 'spam')
Apakah Anda harus menggunakan OrderedDict atau Anda secara spesifik menginginkan tipe seperti peta yang dipesan dengan cara tertentu dengan pengindeksan posisi cepat? Jika yang terakhir, maka pertimbangkan salah satu dari banyak jenis dict diurutkan Python (yang memesan pasangan nilai kunci berdasarkan urutan kunci). Beberapa implementasi juga mendukung pengindeksan cepat. Misalnya, proyek Sortcontainers memiliki tipe SortedDict hanya untuk tujuan ini.
>>> 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
dengan fungsi tombol untuk menghindari perbandingan. Seperti: SortedDict(lambda key: 0, ...)
. Kunci kemudian tidak akan disortir tetapi akan tetap dalam urutan stabil dan dapat diindeks.
Ini adalah kasus khusus jika Anda ingin entri pertama (atau dekat dengan itu) di dalam OrderedDict, tanpa membuat daftar. (Ini telah diperbarui ke Python 3):
>>> 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'
(Pertama kali Anda mengatakan "next ()", itu benar-benar berarti "pertama.")
Dalam tes informal saya, next(iter(d.items()))
dengan OrderedDict kecil hanya sedikit lebih cepat daripada items()[0]
. Dengan OrderedDict dari 10.000 entri, next(iter(d.items()))
sekitar 200 kali lebih cepat daripada items()[0]
.
TETAPI jika Anda menyimpan daftar item () sekali dan kemudian menggunakan banyak daftar, itu bisa lebih cepat. Atau jika Anda berulang kali {membuat item () iterator dan melangkah melaluinya ke posisi yang Anda inginkan}, itu bisa lebih lambat.
OrderedDict
s tidak memiliki iteritems()
metode, sehingga Anda akan perlu melakukan hal berikut untuk mendapatkan item pertama: next(iter(d.items()))
.
d.items()
sepertinya tidak menjadi iterator, jadi iter di depan tidak akan membantu? Itu masih akan mengembalikan daftar lengkap :(
odict_iterator
dan dikonfirmasi kepada saya di IRC #python bahwa ini tidak membuat salinan daftar.
Secara dramatis lebih efisien menggunakan IndexedOrderedDict dari indexed
paket.
Mengikuti komentar Niklas, saya telah melakukan benchmark pada OrderedDict dan IndexedOrderedDict dengan 1000 entri.
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 adalah ~ 100 kali lebih cepat dalam elemen pengindeksan pada posisi tertentu dalam kasus khusus ini.
indexed.py
alih-alih indexed
.
Wiki komunitas ini berupaya mengumpulkan jawaban yang ada.
Python 2.7
Dalam python 2, keys()
, values()
, dan items()
fungsi dari OrderedDict
daftar kembali. Menggunakan values
sebagai contoh, cara paling sederhana adalah
d.values()[0] # "python"
d.values()[1] # "spam"
Untuk koleksi besar di mana Anda hanya peduli pada satu indeks, Anda dapat menghindari membuat daftar lengkap menggunakan versi generator iterkeys
,, itervalues
dan iteritems
:
import itertools
next(itertools.islice(d.itervalues(), 0, 1)) # "python"
next(itertools.islice(d.itervalues(), 1, 2)) # "spam"
The indexed.py menyediakan paket IndexedOrderedDict
, yang dirancang untuk kasus penggunaan ini dan akan menjadi pilihan tercepat.
from indexed import IndexedOrderedDict
d = IndexedOrderedDict({'foo':'python','bar':'spam'})
d.values()[0] # "python"
d.values()[1] # "spam"
Menggunakan itervalues bisa menjadi jauh lebih cepat untuk kamus besar dengan akses acak:
$ 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 memiliki dua opsi dasar yang sama (list vs generator), tetapi metode dict mengembalikan generator secara default.
Metode daftar:
list(d.values())[0] # "python"
list(d.values())[1] # "spam"
Metode generator:
import itertools
next(itertools.islice(d.values(), 0, 1)) # "python"
next(itertools.islice(d.values(), 1, 2)) # "spam"
Kamus Python 3 adalah urutan besarnya lebih cepat dari python 2 dan memiliki speedup serupa untuk menggunakan generator.
+--------+-----------+----------------+---------+
| size | list (ms) | generator (ms) | indexed |
+--------+-----------+----------------+---------+
| 1000 | .0316 | .0165 | .00262 |
| 10000 | .288 | .166 | .00294 |
| 100000 | 3.53 | 1.48 | .00332 |
+--------+-----------+----------------+---------+
Ini adalah era baru dan dengan kamus Python 3.6.1 sekarang mempertahankan pesanan mereka. Semantik ini tidak eksplisit karena itu akan membutuhkan persetujuan BDFL. Tapi Raymond Hettinger adalah yang terbaik berikutnya (dan lebih lucu) dan dia membuat kasus yang cukup kuat bahwa kamus akan dipesan untuk waktu yang sangat lama.
Jadi sekarang mudah untuk membuat irisan kamus:
test_dict = {
'first': 1,
'second': 2,
'third': 3,
'fourth': 4
}
list(test_dict.items())[:2]
Catatan: Pelestarian urutan penyisipan diktonari sekarang resmi di Python 3.7 .
untuk OrderedDict () Anda dapat mengakses elemen dengan mengindeks dengan mendapatkan tupel pasangan (kunci, nilai) sebagai berikut atau menggunakan '.values ()'
>>> 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
metode mengembalikan objek tampilan kamus interable daripada daftar, dan tidak mendukung slicing atau pengindeksan. Jadi, Anda harus mengubahnya menjadi daftar terlebih dahulu. docs.python.org/3.3/library/stdtypes.html#dict-views