2012-05-15 5 views
22

나는 항목이 가득한 사전이 있습니다. 하나의 임의 항목을 들여다보고 싶습니다.사전에서 임의의 요소에 액세스 할 Pythonic 방법

print "Amongst our dictionary's items are such diverse elements as: %s" % arb(dictionary) 

어떤 항목에 상관하지 않습니다. 임의로 일 필요는 없습니다.

나는 이것을 구현하는 여러 가지 방법을 생각할 수 있지만 모두 낭비되는 것 같습니다. 파이썬에서 선호하는 숙어가 있는지 궁금하다. 하나라도 빠뜨린다면 파이썬에서 선호하는 관용구가 있는지 궁금하다.

def arb(dictionary): 
# Creates an entire list in memory. Could take a while. 
    return list(dictionary.values())[0] 

def arb(dictionary): 
# Creates an entire interator. An improvement. 
    for item in dictionary.itervalues(): 
     return item 

def arb(dictionary): 
# No iterator, but writes to the dictionary! Twice! 
    key, value = dictionary.popitem() 
    dictionary[key] = value 
    return value 

나는 성능이 충분히 위험 (아직)이 문제는, 그래서이 조기 최적화 비난 할 수없는 위치에있어,하지만 난, 그래서 만약 내 파이썬 코딩 스타일을 개선하기 위해 노력하고 있어요 쉽게 이해할 수있는 변종이있다. 그것을 채택하는 것이 좋을 것이다. 이것은 파이썬 3에서뿐만 아니라 파이썬 2에서 작동하지만, 파이썬 2에서이 같이 그렇게하는 것이 더 효율적이다

return next(iter(dictionary.values())) 

: 내 생각에, 두 번째 솔루션 비슷하지만 약간 더 분명

+7

'dictionary.itervalues ​​(). next()는 어떨까요? 적어도 두 번째'arb' 함수보다 좋을 것입니다. – srgerg

+0

@sgerg 제출할 예정 이었지만 앞으로 나아갈 것입니다. : D – jamylak

+0

그들은 전화를 통해 다른 항목이 필요합니까?이 모든 것들은 같은 항목을 반환 할 것입니다 ... –

답변

26

:

return next(dictionary.itervalues()) 
+0

을 써야합니다. – jamylak

+4

dict이 비어 있으면 StopIteration이 발생합니다. – yak

+5

그러나 'StopIteration'을 피하려면 기본값을 지정할 수 있습니다. 'next (dictionary.itervalues ​​(), None)'. –

1

random을 사용하지 않는 이유는 무엇입니까?

import random 

def arb(dictionary): 
    return random.choice(dictionary.values()) 

이 결과는 구현 부작용을 순전히 임의 될 운명되지 않으며, 그것은 분명 것으로한다. 성능이 실제 문제가 될 때까지 항상 속도에 대한 명확성을 유지하십시오.

dict_values가 색인 생성을 지원하지 않는다는 점은 수치 스러운데, 대신 값보기를 전달할 수 있다면 좋을 것입니다.

업데이트 : 모두 성능에 집착하기 때문에 위의 함수는 1 억 항목의 임의 값에서 임의의 값을 반환하기 위해 < 120ms를 사용합니다. 명확한 코드에 의존하는 것은 놀라운 성능이 아니라는 것을 의미합니다. 전체 values/itervalues/viewvalues 혼란을 방지

+2

선택한 요소가 임의 일 필요가없는 것으로 지정된 경우 이는 시간 낭비입니다. 문서화 문자열 (및 이름!)은 그러한 관찰을 위해 전적으로 충분합니다. –

+1

이름이 '임의'이고 키를 반복하는 동작 인 경우 해당 이름이 나에게 명확하지 않으므로 문서화 문자열이 필요합니다. 코드가 왜 보이지 않는지 설명하기 위해 문서화 문자열을 작성해야한다면, 아마도 답은 더 명확한 코드를 작성하는 것일 수 있습니다. –

+1

120 ms는 이와 같은 작업에는 전혀 적합하지 않습니다. 이것은 마이크로 초 이내에 완료되어야합니다. 이전에'd [next (iter (d))]'를 사용했던 곳에서 이것을 넣으면 응용 프로그램이 말 그대로 백만 배 더 느려질 수 있습니다. – user2357112

10

, 이것은 당신이 발전기

next(dictionary[x] for x in dictionary) 
+0

당신은 단순히'next (iter (dictionary.values ​​()))' –

+0

@ Ev.Kounis도 할 수 있지만, python2에서는 추가리스트를 생성합니다. –

+0

'map'도 파이썬 2에서리스트를 생성합니다. – user2357112

2

내가 질문 크게 대답되었다고 생각 연산 식을 선호 택일 경우 Python2 또는 Python3

dictionary[next(iter(dictionary))] 

에서 동일하게 작동 그러나이 비교가 클린 코드와 시간의 트레이드 오프를 밝혀 줄 것입니다 :

from timeit import timeit 
from random import choice 
A = {x:[y for y in range(100)] for x in range(1000)} 
def test_pop(): 
    k, v= A.popitem() 
    A[k] = v 

def test_iter(): k = next(A.iterkeys()) 

def test_list(): k = choice(A.keys()) 

def test_insert(): A[0] = 0 

if __name__ == '__main__': 
    print('pop', timeit("test_pop()", setup="from __main__ import test_pop", number=10000)) 
    print('iter', timeit("test_iter()", setup="from __main__ import test_iter", number=10000)) 
    print('list', timeit("test_list()", setup="from __main__ import test_list", number=10000)) 
    print('insert', timeit("test_insert()", setup="from __main__ import test_insert", number=10000)) 

다음은 결과입니다 :

('pop', 0.0021750926971435547) 
('iter', 0.002003908157348633) 
('list', 0.047267913818359375) 
('insert', 0.0010859966278076172) 

그것은 iterkeys를 사용하는 경우에만 한계 빨리 다음 항목을 저런 애하고 10 배의 빠른 목록을 작성하고 그것에서 임의의 객체를 선택 후 재 - 삽입하지만 것 같다.

관련 문제