Iterating over every two elements in a list

2018-12-31 04:18发布

How do I make a for loop or a list comprehension so that every iteration gives me two elements?

l = [1,2,3,4,5,6]

for i,k in ???:
    print str(i), '+', str(k), '=', str(i+k)

Output:

1+2=3
3+4=7
5+6=11

标签: python list
19条回答
忆尘夕之涩
2楼-- · 2018-12-31 05:11

In case you're interested in the performance, I did a small benchmark to compare the performance of the solutions and I included a function from one of my packages: iteration_utilities.grouper

def Johnsyweb(l):
    def pairwise(iterable):
        "s -> (s0, s1), (s2, s3), (s4, s5), ..."
        a = iter(iterable)
        return zip(a, a)

    for x, y in pairwise(l):
        pass

def Margus(data):
    for i, k in zip(data[0::2], data[1::2]):
        pass

def pyanon(l):
    list(zip(l,l[1:]))[::2]

def taskinoor(l):
    for i in range(0, len(l), 2):
        l[i], l[i+1]

def mic_e(it):
    def pairwise(it):
        it = iter(it)
        while True:
            try:
                yield next(it), next(it)
            except StopIteration:
                return

    for a, b in pairwise(it):
        pass

def MSeifert(it):
    for item1, item2 in grouper(it, 2):
        pass

from iteration_utilities import grouper
from simple_benchmark import benchmark_random_list

b = benchmark_random_list(
    [Johnsyweb, Margus, pyanon, taskinoor, mic_e, MSeifert],
    sizes=[2**i for i in range(1, 20)])

b.plot_both(relative_to=MSeifert)

enter image description here

Windows 10 64 bit Anaconda Python 3.6

So if you want the fastest solution without external dependencies you probably should just use the approach given by Johnysweb (at the time of writing it's the most upvoted and accepted answer).

If you don't mind the additional dependency then the grouper from iteration_utilities will probably be a bit faster.

Additional thoughts

Some of the approaches have some restrictions, that haven't been discussed here.

For example a few solutions only work for sequences (that is lists, strings, etc.), for example Margus/pyanon/taskinoor solutions which uses indexing while other solutions work on any iterable (that is sequences and generators, iterators) like Johnysweb/mic_e/my solutions.

Then Johnysweb also provided a solution that works for other sizes than 2 while the other answers don't (okay, the iteration_utilities.grouper also allows setting the number of elements to "group").

Then there is also the question about what should happen if there is an odd number of elements in the list. Should the remaining item be dismissed? Should the list be padded to make it even sized? Should the remaining item be returned as single? The other answer don't address this point directly, however if I haven't overlooked anything they all follow the approach that the remaining item should be dismissed (except for taskinoors answer - that will actually raise an Exception).

With grouper you can decide what you want to do:

>>> from iteration_utilities import grouper

>>> list(grouper([1, 2, 3], 2))  # as single
[(1, 2), (3,)]

>>> list(grouper([1, 2, 3], 2, truncate=True))  # ignored
[(1, 2)]

>>> list(grouper([1, 2, 3], 2, fillvalue=None))  # padded
[(1, 2), (3, None)]
查看更多
登录 后发表回答