컬렉션의 항목에 액세스합니다.


142

다음 코드가 있다고 가정 해 보겠습니다.

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

다음과 같이 번호가 매겨진 방식으로 항목에 액세스 할 수있는 방법이 있습니까?

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

답변:


181

그것의 경우 OrderedDict()다음과 같이 (키, 값) 쌍의 튜플을 가져 와서 인덱싱하여 요소에 쉽게 액세스 할 수 있습니다

>>> 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목록이 아닌 반복 가능한 dict view 객체를 반환 합니다. 인덱싱을 가능하게하기 위해 호출을 목록으로 감싸 야합니다.

>>> 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
Peter DeGlopper

8
큰 dictonaries의 경우 항목, 값 또는 키를 목록에 복사하면 속도가 느려질 수 있습니다. : 나는 매우 자주이 작업을 수행 할 수있는 응용 프로그램에 대해 다른 내부 자료 구조와 OrderedDict ()의 재 작성을 만들어 github.com/niklasf/indexed.py
니클라스

1
@PeterDeGlopper 목록으로 바꾸려면 어떻게해야합니까?
Dejell

1
@Dejel-생성자를 사용하십시오 :list(d.items())
Peter DeGlopper

9
만 액세스 한 항목 경우 오버 헤드의 기억을 피할 수 있습니다 list(d.items())사용하여 next(islice(d.items(), 1))얻을 수('bar', 'spam')
Quantum7

24

OrderedDict를 사용해야합니까, 아니면 빠른 위치 색인 방식으로 정렬 된 맵과 같은 유형을 구체적으로 원하십니까? 후자의 경우 파이썬의 많은 정렬 된 dict 유형 중 하나 (키 정렬 순서에 따라 키-값 쌍을 정렬)를 고려하십시오. 일부 구현은 빠른 인덱싱도 지원합니다. 예를 들어 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, ...). 그런 다음 키는 정렬되지 않지만 안정적인 순서로 유지되며 색인을 생성 할 수 있습니다.
GrantJ

19

다음은 목록을 만들지 않고 OrderedDict에서 첫 번째 항목 (또는 그에 가까운 항목) 을 원하는 경우의 특별한 경우 입니다. (이것은 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'

(처음으로 "next ()"라고 말하면 실제로 "처음"을 의미합니다.)

비공식 테스트에서 next(iter(d.items()))작은 OrderedDict를 사용하는 것보다 약간 빠릅니다 items()[0]. 10,000 개 항목의 OrderedDict를 사용하면 next(iter(d.items()))보다 약 200 배 빠릅니다 items()[0].

그러나 items () 목록을 한 번 저장 한 다음 목록을 많이 사용하면 더 빠를 수 있습니다. 또는 반복적으로 {items () 반복자를 만들고 원하는 위치로 단계별로 이동하면 느려질 수 있습니다.


10
파이썬 3 OrderedDict에는 iteritems()메소드가 없으므로 첫 번째 항목을 얻으려면 다음을 수행해야합니다 next(iter(d.items())).
Nathan Osman

파이썬 3 d.items()에서는 이터레이터가 아닌 것 같습니다. 여전히 전체 목록을 반환합니다 :(
asksol

1
업데이트 : 나는 틀렸고 iter (d.items ())가 반환 odict_iterator하고 IRC #python에서 이것이 목록의 사본을 만들지 않는다는 것을 확인했습니다.
asksol

@Nathan Osman, 너지 고마워. 나는 최근에 Python 3으로 자신을 마침내 업데이트했습니다!
SteveWitham4

14

에서 IndexedOrderedDict 를 사용하는 것이 훨씬 더 효율적 입니다.indexed패키지 입니다.

Niklas의 의견에 따라 1000 개의 항목 으로 OrderedDictIndexedOrderedDict 에 대한 벤치 마크를 수행했습니다 .

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 배 빠릅니다.


좋은! 불행히도 아나콘다에는 아직 없습니다.
Konstantin

1
패키지의 실제 이름 @Konstantin입니다 indexed.py . indexed.py대신 설치해보십시오 indexed.
Sven Haile

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"

랜덤 액세스를 사용하는 큰 사전의 경우 itervalue를 사용하는 것이 훨씬 빠를 수 있습니다.

$ 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

Python 3에는 동일한 두 가지 기본 옵션 (목록과 생성기)이 있지만 dict 메서드는 기본적으로 생성기를 반환합니다.

목록 방법 :

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

새로운 시대이며 Python 3.6.1 사전은 이제 순서를 유지합니다. 이 의미는 BDFL 승인이 필요하기 때문에 명시 적이 지 않습니다. 그러나 레이몬드 Hettinger는 차선책 (그리고 더 재미)이며, 그는하게 꽤 강한 케이스 사전은 아주 긴 시간 동안 주문 것입니다.

이제 사전 조각을 쉽게 만들 수 있습니다.

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

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

참고 : Dictonary 삽입 순서 보존은 이제 Python 3.7에서 공식화되었습니다 .


0

OrderedDict ()의 경우 다음과 같이 (키, 값) 쌍의 튜플을 가져 오거나 '.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']
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.