एक संग्रह में आइटम तक पहुँच। सूचकांक द्वारा संपादित


142

आइए बताते हैं कि मेरे पास निम्नलिखित कोड हैं:

import collections
d = collections.OrderedDict()
d['foo'] = 'python'
d['bar'] = 'spam'

क्या कोई ऐसा तरीका है जिससे मैं आइटम को गिने तरीके से एक्सेस कर सकता हूं, जैसे:

d(0) #foo's Output
d(1) #bar's Output

जवाबों:


181

अगर इसकी एक OrderedDict()आप आसानी से (कुंजी, मूल्य) जोड़े के tuples द्वारा अनुक्रमण द्वारा तत्वों का उपयोग कर सकते हैं निम्नानुसार है

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

पायथन 3.X के लिए ध्यान दें

dict.itemsएक सूची के बजाय एक पुन: प्रयोज्य तानाशाही वस्तु लौटाएगा । अनुक्रमण को संभव बनाने के लिए हमें कॉल को सूची में लपेटना होगा

>>> items = list(d.items())
>>> items
[('foo', 'python'), ('bar', 'spam')]
>>> items[0]
('foo', 'python')
>>> items[1]
('bar', 'spam')

21
ध्यान दें कि 3.x में itemsविधि एक सूची के बजाय एक अंतरयोग्य शब्दकोश दृश्य वस्तु लौटाती है, और स्लाइसिंग या अनुक्रमण का समर्थन नहीं करती है। इसलिए आपको इसे पहले एक सूची में बदलना होगा। docs.python.org/3.3/library/stdtypes.html#dict-views
पीटर

8
सूचियों में वस्तुओं, मूल्यों या कुंजियों की नकल करना बड़े तानाशाहों के लिए काफी धीमा हो सकता है। मैंने कई बार ऐसा करने वाले अनुप्रयोगों के लिए एक अलग आंतरिक डेटास्ट्रक्चर के साथ आर्डर डिडक्ट () का पुनर्लेखन किया: github.com/niklasf/indexed.py
Niklas

1
@PeterDeGlopper मैं इसे सूची में कैसे बदलूं?
देजेल

1
@ डेजेल - कंस्ट्रक्टर का उपयोग करें:list(d.items())
पीटर डेगॉपर

9
आप केवल एक आइटम का उपयोग कर सकते हैं, तो आप की भूमि के ऊपर स्मृति से बच सकते हैं list(d.items())का उपयोग करके next(islice(d.items(), 1))प्राप्त करने के लिए('bar', 'spam')
Quantum7

24

क्या आपको किसी ऑर्डरडेड का उपयोग करना है या क्या आप विशेष रूप से एक मानचित्र-प्रकार चाहते हैं जो किसी तरह से तेजी से स्थितीय अनुक्रमण के साथ आदेश दिया गया है? यदि उत्तरार्द्ध, तो पायथन के कई सॉर्ट किए गए तानाशाह प्रकारों में से एक पर विचार करें (जो कुंजी क्रम के आधार पर कुंजी-मूल्य जोड़े का आदेश देता है)। कुछ कार्यान्वयन तेजी से अनुक्रमण का समर्थन भी करते हैं। उदाहरण के लिए, Sortedcontainers प्रोजेक्ट में केवल इस उद्देश्य के लिए SortedDict प्रकार होता है।

>>> 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'

1
SortedDictतुलना से बचने के लिए आप एक प्रमुख फ़ंक्शन का उपयोग कर सकते हैं । जैसा: SortedDict(lambda key: 0, ...)। कीज़ तो अनसोल्ड रहेंगे लेकिन स्थिर क्रम में रहेंगे और इंडेक्सेबल होंगे।
ग्रांटज

19

यहां एक विशेष मामला है यदि आप एक सूची बनाए बिना एक ऑर्डरडीड में पहली प्रविष्टि (या इसके करीब) चाहते हैं। (इसे पायथन 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'

(पहली बार जब आप "अगला ()" कहते हैं, तो इसका वास्तव में अर्थ है "पहले।")

मेरे अनौपचारिक परीक्षण में, next(iter(d.items()))एक छोटे से आदेश के साथ केवल एक छोटा सा तेजी से होता है items()[0]। 10,000 प्रविष्टियों के ऑर्डरडीड के साथ, next(iter(d.items()))लगभग 200 गुना तेजी से था items()[0]

लेकिन यदि आप आइटम () सूची को एक बार सहेजते हैं और फिर सूची का उपयोग करते हैं, तो यह तेज हो सकता है। या यदि आप बार-बार {एक आइटम बनाते हैं () पुनरावृत्ति करें और उसके माध्यम से उस स्थान पर कदम बढ़ाएं जो आप चाहते हैं}, तो यह धीमा हो सकता है।


10
पायथन 3 OrderedDictएस में एक iteritems()विधि नहीं है , इसलिए आपको पहला आइटम प्राप्त करने के लिए निम्नलिखित करने की आवश्यकता होगी next(iter(d.items())):।
नाथन उस्मान

पायथन 3 में d.items()एक पुनरावृत्ति नहीं लगती है, इसलिए सामने वाला मदद नहीं करेगा? यह अभी भी पूरी सूची
लौटाएगा

1
अद्यतन: मैं गलत था, iter (d.items ()) रिटर्न odict_iteratorऔर IRC #python पर मुझे पुष्टि की गई थी कि यह सूची की प्रतिलिपि नहीं बनाता है।
अस्कोल

@ नथन उस्मान, आभार के लिए धन्यवाद। मैंने आखिरकार हाल ही में पायथन 3 में खुद को अपडेट किया!
स्टीवविथम डुप्लिकेट

14

यह उपयोग करने के लिए नाटकीय रूप से और अधिक कुशल है IndexedOrderedDict सेindexed पैकेज ।

निकलास की टिप्पणी के बाद, मैंने 1000 प्रविष्टियों के साथ ऑर्डरडीड और इंडेक्सऑर्डरड्रेडडिक्ट पर एक बेंचमार्क किया है ।

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 इस विशिष्ट मामले में विशिष्ट स्थिति में तत्वों को अनुक्रमित करने में ~ 100 गुना तेज है।


अच्छा! दुर्भाग्य से अभी तक एनाकोंडा में नहीं है।
कॉन्स्टेंटिन

1
@Konstantin पैकेज का वास्तविक नाम indexed.py है । के indexed.pyबजाय स्थापित करने का प्रयास करें indexed
स्वेन हेल

9

यह समुदाय मौजूदा उत्तरों को एकत्र करने का प्रयास करता है।

पायथन 2.7

अजगर 2 में keys(), values()और items()के कार्यों OrderedDictवापसी सूचियों। valuesएक उदाहरण के रूप में उपयोग करना , सबसे सरल तरीका है

d.values()[0]  # "python"
d.values()[1]  # "spam"

बड़े संग्रहों के लिए जहां आप केवल एक इंडेक्स की परवाह करते हैं, आप जनरेटर संस्करणों का उपयोग करके पूरी सूची बनाने से बच सकते हैं iterkeys, itervaluesऔर iteritems:

import itertools
next(itertools.islice(d.itervalues(), 0, 1))  # "python"
next(itertools.islice(d.itervalues(), 1, 2))  # "spam"

Indexed.py पैकेज प्रदान करता है IndexedOrderedDict, जो उपयोग के इस मामले डिज़ाइन किया गया है और सबसे तेजी से विकल्प होगा।

from indexed import IndexedOrderedDict
d = IndexedOrderedDict({'foo':'python','bar':'spam'})
d.values()[0]  # "python"
d.values()[1]  # "spam"

यादृच्छिक उपयोग के साथ बड़े शब्दकोशों के लिए itervalues ​​का उपयोग करना काफी तेज़ हो सकता है:

$ 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  |
+--------+-----------+----------------+---------+

अजगर 3.6

पायथन 3 में एक ही दो मूल विकल्प हैं (सूची बनाम जनरेटर), लेकिन डिफ़ॉल्ट तरीके डिफ़ॉल्ट रूप से जनरेटर लौटाते हैं।

सूची विधि:

list(d.values())[0]  # "python"
list(d.values())[1]  # "spam"

जनरेटर विधि:

import itertools
next(itertools.islice(d.values(), 0, 1))  # "python"
next(itertools.islice(d.values(), 1, 2))  # "spam"

अजगर 3 शब्दकोशों अजगर 2 की तुलना में तेजी का एक क्रम है और जनरेटर का उपयोग करने के लिए समान गति है।

+--------+-----------+----------------+---------+
|  size  | list (ms) | generator (ms) | indexed |
+--------+-----------+----------------+---------+
|   1000 | .0316     | .0165          | .00262  |
|  10000 | .288      | .166           | .00294  |
| 100000 | 3.53      | 1.48           | .00332  |
+--------+-----------+----------------+---------+

7

यह एक नया युग है और पायथन 3.6.1 शब्दकोशों के साथ अब अपना क्रम बनाए रखते हैं। ये शब्दार्थ स्पष्ट नहीं हैं क्योंकि इसके लिए BDFL की मंजूरी की आवश्यकता होगी। लेकिन रेमंड हेटिंगर अगली सबसे अच्छी चीज़ (और फ़नियर) है और वह एक बहुत मजबूत मामला बनाता है कि बहुत लंबे समय के लिए शब्दकोशों का आदेश दिया जाएगा।

तो अब एक शब्दकोश के स्लाइस बनाना आसान है:

test_dict = {
                'first':  1,
                'second': 2,
                'third':  3,
                'fourth': 4
            }

list(test_dict.items())[:2]

नोट: डिक्टोनरी सम्मिलन-आदेश संरक्षण अब पायथन 3.7 में आधिकारिक है


0

ऑर्डरडीडिक्ट () के लिए आप (कुंजी, मूल्य) जोड़े के ट्यूपल्स को अनुक्रमणिका द्वारा अनुक्रमण द्वारा तत्वों का उपयोग कर सकते हैं।

>>> 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']
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.