다음을 가정하십시오.
>>> s = set([1, 2, 3])
내가 s
하지 않고 어떻게 가치 (값)를 얻 s.pop()
습니까? 항목을 제거 할 수있을 때까지 항목을 세트에 남겨두고 싶습니다. 다른 호스트에 대한 비동기 호출 후에 만 확인할 수있는 것입니다.
빠르고 더러운 :
>>> elem = s.pop()
>>> s.add(elem)
그러나 더 나은 방법을 알고 있습니까? 일정한 시간에 이상적입니다.
답변
전체 세트를 복사하지 않아도되는 두 가지 옵션 :
for e in s:
break
# e is now an element from s
또는…
e = next(iter(s))
그러나 일반적으로 세트는 인덱싱 또는 슬라이싱을 지원하지 않습니다.
답변
가장 작은 코드는 다음과 같습니다.
>>> s = set([1, 2, 3])
>>> list(s)[0]
1
분명히 이것은 세트의 각 멤버를 포함하는 새 목록을 생성하므로 세트가 매우 큰 경우 좋지 않습니다.
답변
함수가 다른 세트에서 어떻게 수행되는지 궁금해하여 벤치 마크를 수행했습니다.
from random import sample
def ForLoop(s):
for e in s:
break
return e
def IterNext(s):
return next(iter(s))
def ListIndex(s):
return list(s)[0]
def PopAdd(s):
e = s.pop()
s.add(e)
return e
def RandomSample(s):
return sample(s, 1)
def SetUnpacking(s):
e, *_ = s
return e
from simple_benchmark import benchmark
b = benchmark([ForLoop, IterNext, ListIndex, PopAdd, RandomSample, SetUnpacking],
{2**i: set(range(2**i)) for i in range(1, 20)},
argument_name='set size',
function_aliases={first: 'First'})
b.plot()
이 그림은 일부 접근 방식 ( RandomSample
, SetUnpacking
및 ListIndex
)이 세트의 크기에 따라 다르며 일반적인 경우 (적어도 성능 이 중요 할 수 있는 경우) 피해야 함을 분명히 보여줍니다 . 이미 다른 답변에서 볼 수 있듯이 가장 빠른 방법은 ForLoop
입니다.
그러나 일정한 시간 접근법 중 하나를 사용하는 한 성능 차이는 무시할 수 있습니다.
iteration_utilities
(면책 조항 : 저자입니다)이 사용 사례에 대한 편의 기능이 포함되어 있습니다. first
:
>>> from iteration_utilities import first
>>> first({1,2,3,4})
1
또한 위의 벤치 마크에 포함 시켰습니다. 다른 두 가지 “빠른”솔루션과 경쟁 할 수 있지만 그 차이는 그리 크지 않습니다.
답변
tl; dr
for first_item in muh_set: break
Python 3.x에서 최적의 접근 방식으로 남아 있습니다. 저주, 귀도
너 이거 해
wr 에서 추정 한 또 다른 Python 3.x 타이밍 세트에 오신 것을 환영합니다 . 탁월한 Python 2.x 전용 응답 . AChampion 의 똑같이 유용한 Python 3.x 관련 응답 과는 달리 아래의 타이밍 은 위에서 제안한 이상치 해결책 도 포함합니다.
list(s)[0]
, 존 의 신규 시퀀스 기반 솔루션 .random.sample(s, 1)
, DF. 다양한 RNG 기반 솔루션 .
큰 기쁨을위한 코드 스 니펫
켜고 조정하고 시간을 정하십시오.
from timeit import Timer
stats = [
"for i in range(1000): \n\tfor x in s: \n\t\tbreak",
"for i in range(1000): next(iter(s))",
"for i in range(1000): s.add(s.pop())",
"for i in range(1000): list(s)[0]",
"for i in range(1000): random.sample(s, 1)",
]
for stat in stats:
t = Timer(stat, setup="import random\ns=set(range(100))")
try:
print("Time for %s:\t %f"%(stat, t.timeit(number=1000)))
except:
t.print_exc()
빨리 쓸모없는 영원한 타이밍
보다! 가장 빠르거나 느린 스 니펫으로 정렬 :
$ ./test_get.py
Time for for i in range(1000):
for x in s:
break: 0.249871
Time for for i in range(1000): next(iter(s)): 0.526266
Time for for i in range(1000): s.add(s.pop()): 0.658832
Time for for i in range(1000): list(s)[0]: 4.117106
Time for for i in range(1000): random.sample(s, 1): 21.851104
온 가족을위한 페이스 플랜트
당연히 수동 반복은 다음으로 빠른 솔루션 보다 2 배 이상 빠릅니다 . 수동 반복이 4 배 이상 빠르 던 Bad Old Python 2.x 일과의 격차가 줄어들었지만 가장 장황한 솔루션이 최고라고 PEP 20 열성에 실망했습니다 . 집합의 첫 번째 요소를 추출하기 위해 집합을 목록으로 변환하는 것은 예상만큼 끔찍합니다. 귀도에게 감사합니다. 그의 빛이 우리를 계속 인도 해 주시길 바랍니다.
놀랍게도 RNG 기반 솔루션은 끔찍합니다. 목록 변환은 좋지 않지만 random
실제로 는 끔찍한 소스 케이크가 필요합니다. 난수 신을 위해 너무 많은 .
나는 단지 비정질을 원합니다. 그들은 set.get_first()
이미 우리를 위해 방법을 PEP 할 것 입니다. 이 글을 읽고 있다면, “제발. 뭔가 해봐.”
답변
서로 다른 접근 방식의 일부 타이밍 수치를 제공하려면 다음 코드를 고려하십시오.
get ()은 Python의 setobject.c에 대한 사용자 정의 추가이며 요소를 제거하지 않고 pop () 일뿐입니다.
from timeit import *
stats = ["for i in xrange(1000): iter(s).next() ",
"for i in xrange(1000): \n\tfor x in s: \n\t\tbreak",
"for i in xrange(1000): s.add(s.pop()) ",
"for i in xrange(1000): s.get() "]
for stat in stats:
t = Timer(stat, setup="s=set(range(100))")
try:
print "Time for %s:\t %f"%(stat, t.timeit(number=1000))
except:
t.print_exc()
출력은 다음과 같습니다.
$ ./test_get.py
Time for for i in xrange(1000): iter(s).next() : 0.433080
Time for for i in xrange(1000):
for x in s:
break: 0.148695
Time for for i in xrange(1000): s.add(s.pop()) : 0.317418
Time for for i in xrange(1000): s.get() : 0.146673
이는 for / break 솔루션이 가장 빠르다는 것을 의미합니다 (때로는 사용자 정의 get () 솔루션보다 빠름).
답변
임의의 요소를 원하므로 다음과 같이 작동합니다.
>>> import random
>>> s = set([1,2,3])
>>> random.sample(s, 1)
[2]
설명서에는의 성능에 대해서는 언급되어 있지 않습니다 random.sample
. 방대한 목록과 방대한 집합을 사용하여 실제로 실험적으로 빠르게 테스트 한 결과, 목록에 대해서는 일정한 시간 인 것처럼 보이지만 집합에는 해당되지 않습니다. 또한 집합에 대한 반복은 무작위가 아닙니다. 순서는 정의되지 않았지만 예측 가능합니다.
>>> list(set(range(10))) == range(10)
True
임의성이 중요하고 일정한 시간 (큰 세트)에 많은 요소가 필요한 경우 random.sample
먼저 목록을 사용 하고 변환합니다.
>>> lst = list(s) # once, O(len(s))?
...
>>> e = random.sample(lst, 1)[0] # constant time