단일 목록의 쌍
종종 나는 쌍으로 목록을 처리해야 할 필요성을 발견했습니다. 나는 그것을 수행하는 비단뱀적이고 효율적인 방법이 무엇인지 궁금해했으며 Google에서 이것을 발견했습니다.
pairs = zip(t[::2], t[1::2])
나는 그것이 충분히 비단뱀 적이라고 생각했지만, 최근 관용어 대 효율성에 관한 토론을 한 후 몇 가지 테스트를하기로 결정했습니다.
import time
from itertools import islice, izip
def pairs_1(t):
return zip(t[::2], t[1::2])
def pairs_2(t):
return izip(t[::2], t[1::2])
def pairs_3(t):
return izip(islice(t,None,None,2), islice(t,1,None,2))
A = range(10000)
B = xrange(len(A))
def pairs_4(t):
# ignore value of t!
t = B
return izip(islice(t,None,None,2), islice(t,1,None,2))
for f in pairs_1, pairs_2, pairs_3, pairs_4:
# time the pairing
s = time.time()
for i in range(1000):
p = f(A)
t1 = time.time() - s
# time using the pairs
s = time.time()
for i in range(1000):
p = f(A)
for a, b in p:
pass
t2 = time.time() - s
print t1, t2, t2-t1
내 컴퓨터의 결과는 다음과 같습니다.
1.48668909073 2.63187503815 1.14518594742
0.105381965637 1.35109519958 1.24571323395
0.00257992744446 1.46182489395 1.45924496651
0.00251388549805 1.70076990128 1.69825601578
올바르게 해석하고 있다면 파이썬에서 목록, 목록 인덱싱 및 목록 분할을 구현하는 것이 매우 효율적이라는 것을 의미합니다. 편안함과 예상치 못한 결과입니다.
쌍으로 목록을 순회하는 또 다른 "더 나은"방법이 있습니까?
목록에 홀수 개의 요소가있는 경우 마지막 요소는 쌍에 포함되지 않습니다.
모든 요소가 포함되도록하는 올바른 방법은 무엇입니까?
I added these two suggestions from the answers to the tests:
def pairwise(t):
it = iter(t)
return izip(it, it)
def chunkwise(t, size=2):
it = iter(t)
return izip(*[it]*size)
These are the results:
0.00159502029419 1.25745987892 1.25586485863
0.00222492218018 1.23795199394 1.23572707176
Results so far
Most pythonic and very efficient:
pairs = izip(t[::2], t[1::2])
Most efficient and very pythonic:
pairs = izip(*[iter(t)]*2)
It took me a moment to grok that the first answer uses two iterators while the second uses a single one.
To deal with sequences with an odd number of elements, the suggestion has been to augment the original sequence adding one element (None
) that gets paired with the previous last element, something that can be achieved with itertools.izip_longest()
.
Finally
Note that, in Python 3.x, zip()
behaves as itertools.izip()
, and itertools.izip()
is gone.
My favorite way to do it:
from itertools import izip
def pairwise(t):
it = iter(t)
return izip(it,it)
# for "pairs" of any length
def chunkwise(t, size=2):
it = iter(t)
return izip(*[it]*size)
When you want to pair all elements you obviously might need a fillvalue:
from itertools import izip_longest
def blockwise(t, size=2, fillvalue=None):
it = iter(t)
return izip_longest(*[it]*size, fillvalue=fillvalue)
I'd say that your initial solution pairs = zip(t[::2], t[1::2])
is the best one because it is easiest to read (and in Python 3, zip
automatically returns an iterator instead of a list).
To ensure that all elements are included, you could simply extend the list by None
.
Then, if the list has an odd number of elements, the last pair will be (item, None)
.
>>> t = [1,2,3,4,5]
>>> t.append(None)
>>> zip(t[::2], t[1::2])
[(1, 2), (3, 4), (5, None)]
>>> t = [1,2,3,4,5,6]
>>> t.append(None)
>>> zip(t[::2], t[1::2])
[(1, 2), (3, 4), (5, 6)]
I start with small disclaimer - don't use the code below. It's not Pythonic at all, I wrote just for fun. It's similar to @THC4k pairwise
function but it uses iter
and lambda
closures. It doesn't use itertools
module and doesn't support fillvalue
. I put it here because someone might find it interesting:
pairwise = lambda t: iter((lambda f: lambda: (f(), f()))(iter(t).next), None)
As far as most pythonic goes, I'd say the recipes supplied in the python source docs (some of which look a lot like the answers that @JochenRitzel provided) is probably your best bet ;)
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
Is there another, "better" way of traversing a list in pairs?
I can't say for sure but I doubt it: Any other traversal would include more Python code which has to be interpreted. The built-in functions like zip() are written in C which is much faster.
Which would be the right way to ensure that all elements are included?
Check the length of the list and if it's odd (len(list) & 1 == 1
), copy the list and append an item.
>>> my_list = [1,2,3,4,5,6,7,8,9,10]
>>> my_pairs = list()
>>> while(my_list):
... a = my_list.pop(0); b = my_list.pop(0)
... my_pairs.append((a,b))
...
>>> print(my_pairs)
[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
참고URL : https://stackoverflow.com/questions/4628290/pairs-from-single-list
'IT story' 카테고리의 다른 글
CoordinatorLayout이란 무엇입니까? (0) | 2020.09.14 |
---|---|
프로필이 아닌 페이스 북 페이지의 담벼락에 어떻게 게시합니까? (0) | 2020.09.14 |
맵 인스턴스를 삭제하는 올바른 방법은 무엇입니까? (0) | 2020.09.14 |
Redux와 반응합니까? (0) | 2020.09.14 |
람다 언어는 무엇입니까? (0) | 2020.09.14 |