-2

I have a list of the shape

[1,2,3,4,5,6,7,8]

and how can I turn it into

[(1,2),(3,4),(5,6),(7,8)]

quickly? (The list is large.)

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
NathaneilCapital
  • 1,389
  • 5
  • 17
  • 23
  • 3
    what if the list doesn't have an even number of elements? – Itay Karo Jan 05 '14 at 05:39
  • In my use case, the input data is filtered/checked first to be even. An answer handles odd number in list is definitely welcome. – NathaneilCapital Jan 05 '14 at 07:33
  • possible duplicate of [What is the most "pythonic" way to iterate over a list in chunks?](http://stackoverflow.com/questions/434287/what-is-the-most-pythonic-way-to-iterate-over-a-list-in-chunks) – Wilfred Hughes Feb 20 '14 at 11:46

7 Answers7

6

Use the grouper recipe, which will take care of odd lengths:

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)

Use it like this:

>>> from itertools import izip_longest # needed for grouper helper
>>> list(grouper([1,2,3,4,5,6,7], 2))
[(1, 2), (3, 4), (5, 6), (7, None)]
Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
1

I was thinking of:

a = [1, 2, 3, 4, 5, 6, 7, 8]
print [(a[i], a[i + 1]) for i in xrange(0, len(a) - 1, 2)]

Output:

[(1, 2), (3, 4), (5, 6), (7, 8)]

Note:

This works if the number of elements in the list is odd or even. But if it's odd, it won't generate a tuple with the last element:

a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print [(a[i], a[i + 1]) for i in xrange(0, len(a) - 1, 2)]

Output:

[(1, 2), (3, 4), (5, 6), (7, 8)]
Christian Tapia
  • 33,620
  • 7
  • 56
  • 73
0

Just slice it... It's not that hard:

>>> l = [1,2,3,4,5,6,7,8]
>>> r = []
>>> for i in range(0, len(l), 2):
        r.append(tuple(l[i:i+2]))


>>> print(r)
[(1, 2), (3, 4), (5, 6), (7, 8)]

Or the shorter LC version:

r = [tuple(l[i:i+2]) for i in range(0, len(l), 2)]
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
aIKid
  • 26,968
  • 4
  • 39
  • 65
0

Assuming that the list has an even number of elements:
If the list is large and you can use a pairs generators instead of a list (it will be much faster)...

mylist = [1,2,3,4,5,6,7,8]
pairs = ((myList[i], myList[i+1]) for i in xrange(0, len(myList), 2))

If you must have a resulting list - use a list comprehension as suggested in other answers

[(myList[i], myList[i+1]) for i in xrange(0, len(myList), 2)]
Itay Karo
  • 17,924
  • 4
  • 40
  • 58
0

Simply run over one iterator of the list, grabbing two entries each time. zip will let you do this quite nicely.

from itertools import izip_longest
# assuming you are on Python 2
# if you are on Python 3 this is zip_longest

your_list = range(22)

# First, make an iterator for the list
iterator = iter(your_list)

# Then grab two entries from the iterator
# each iteration (using zip, but you could also
# use x, y = next(iterator), next(iterator)
# if you wanted to be *really* explicit.
results = izip_longest(iterator, iterator)
for val in results:
    print val

# (0, 1)
# (2, 3)
# (4, 5)
# ... etc. ...
Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
0

The list comprehension in thefourtheye's answer will work.

Another possibility is to use a recipe based off of the itertools module's izip_longest function, as detailed in this answer:

from itertools import izip_longest
def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

pairs = map(tuple, grouper(2, [1,2,3,4,5,6,7,8]))
# [(1, 2), (3, 4), (5, 6), (7, 8)]
Community
  • 1
  • 1
Platinum Azure
  • 45,269
  • 12
  • 110
  • 134
0

There's the most concise way if the list is even or you don't care about the odd value:

x = range(10)
zip(x[::2], x[1::2])

Or if the list is odd:

import itertools as it

x = range(11)
list(it.izip_longest(x[::2], x[1::2], fillvalue=x[-1]+1))

Or the complete iterator way if you don't want to create lists in memory:

import itertools as it

x = xrange(10000001) # Or really long, maybe infinite iterator
pg = it.izip_longest(it.islice(x,0,None,2), it.islice(x,1,None,2), fillvalue=10000000000)
for pair in pg:
    print pair
fivetentaylor
  • 1,277
  • 7
  • 11