문제
가 다음과 같다:
>>> s = set([1, 2, 3])
어떻게 받을 수 있 value(값)의 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
분명 이들 새로운 목록에 포함하는 각 멤버의 설정,그렇지 않으면 설정이 매우 큰 것입니다.
를 제공합 타이밍 그림 뒤에 서로 다른 접근,다음과 같은 코드를 살펴봅니다.Get()은 내 사용자 지정한 파이썬의 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
즉 에 대한/break 해결책이 가장 빠르다(때로는 보다 빠른 주문을 얻을()솔루션).
tl;박사
for first_item in muh_set: break
남아 최적의 접근 방식에서는 Python3.x. 저주를,Guido.
이렇게
환 또 다른 설정의 Python3.x 타이밍,에서 추정 wr.의 우수한 Python2.x-특정 응답.달리 AChampion's 동등하게 도움이 Python3.x-특정 응답, 타이밍이 아래 도 시간 이상값 솔루션을 제안된 상 포함하여:
list(s)[0]
, John's novel 순서를 기반 솔루션.random.sample(s, 1)
, dF.'s eclectic 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
니다.온 가족을위한
당연히, 수동 반복에 남아 있는 두 배 이상 빠르 으로 다음이 가장 빠른 솔루션입니다.지만 간격은 감소에서 나쁜 오래된 Python2.×일(에서는 수동 반복 최소 네 배로 빠른),그것은 실망하 PEP20 날에 열광하는 가장 자세한 솔루션이 최고입니다.에서 이상으로 변환한 설정으로 목록을 추출하는 첫 번째 요소의 세트로 예상된다. 감사 Guido 수 있습니다,그의 빛이 계속드립니다.
놀랍게도, RNG 기반 솔루션이 절대적으로 끔찍하다. 목록에 변환,나쁘지 random
말 는 끔찍한 소스 케이크입니다.그래서 많 임의의 숫자는 하나님.
제조직들은 격려 set.get_first()
방법은 우리를 위해 이미 이다.당신이 이것을 읽는 경우,그들은:"시기 바랍니다.무언가를 하십시오."
때문에 당신이 원하는 임의의 요소,이 또한 작동합니다:
>>> 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
궁금하는 방법 기능을 수행에 대한 다른 세트,그래서 내가 기준:
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
나 또한 그것을 포함하는지에서 위에 있는 벤치마크.그것은 경쟁 할 수 있습으로 다른 두"빠른"솔루션이지만 차이가 없거나 방법입니다.
내가 사용 유틸리티 기능을 썼다.그것의 이름은 오해의 소지가 다소기 때문에 그것의 종류를 의미할 수 있 임의 항목입니다.
def anyitem(iterable):
try:
return iter(iterable).next()
except StopIteration:
return None
다음@wr.게시물에,나는 이와 유사한 결과를 얻을 수(대 Python3.5)
from timeit import *
stats = ["for i in range(1000): next(iter(s))",
"for i in range(1000): \n\tfor x in s: \n\t\tbreak",
"for i in range(1000): s.add(s.pop())"]
for stat in stats:
t = Timer(stat, setup="s=set(range(100000))")
try:
print("Time for %s:\t %f"%(stat, t.timeit(number=1000)))
except:
t.print_exc()
출력:
Time for for i in range(1000): next(iter(s)): 0.205888
Time for for i in range(1000):
for x in s:
break: 0.083397
Time for for i in range(1000): s.add(s.pop()): 0.226570
그러나 변경하는 경우 기본 설정(예를 들어,전화 remove()
)가 나쁘게 반복 가능한 예(for
, iter
):
from timeit import *
stats = ["while s:\n\ta = next(iter(s))\n\ts.remove(a)",
"while s:\n\tfor x in s: break\n\ts.remove(x)",
"while s:\n\tx=s.pop()\n\ts.add(x)\n\ts.remove(x)"]
for stat in stats:
t = Timer(stat, setup="s=set(range(100000))")
try:
print("Time for %s:\t %f"%(stat, t.timeit(number=1000)))
except:
t.print_exc()
결과:
Time for while s:
a = next(iter(s))
s.remove(a): 2.938494
Time for while s:
for x in s: break
s.remove(x): 2.728367
Time for while s:
x=s.pop()
s.add(x)
s.remove(x): 0.030272
는 방법에 대 s.copy().pop()
?난 그것을 초과하지만,그것은 작동한다고 그것은 간단합니다.그것은 최고의 작품은 세트는 그러나,그것이 복사본을 전체를 설정합니다.
또 다른 옵션은 사전을 사용하는 값으로 당신은 걱정하지 않는다.E.g.,
poor_man_set = {}
poor_man_set[1] = None
poor_man_set[2] = None
poor_man_set[3] = None
...
치료할 수 있습으로 키 설정을 제외하고는 그들은 단지 배열:
keys = poor_man_set.keys()
print "Some key = %s" % keys[0]
이 선택은 당신의 코드가 호환로,사전set
versions of Python.그것은 어쩌면 최고 대답을 하지만 그것은 또 다른 옵션입니다.
편집:도 수행할 수 있습 같은 것이 이 사실을 숨기는 것을 사용한 영어 대신에 배열이나 설정:
poor_man_set = {}
poor_man_set[1] = None
poor_man_set[2] = None
poor_man_set[3] = None
poor_man_set = poor_man_set.keys()