4

I want to convert a list like this

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

to

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

because want to loop

for x,y in l2:
    draw_thing(x,y)
Crescent Fresh
  • 115,249
  • 25
  • 154
  • 140
lgwest
  • 1,347
  • 5
  • 16
  • 26
  • 1
    This comes up a lot. Here the more general case for groups of N: http://stackoverflow.com/questions/1624883/alternative-way-to-split-a-list-into-groups-of-n/1625043#1625043 – u0b34a0f6ae Oct 29 '09 at 21:15

9 Answers9

10

One good way is:

from itertools import izip
it = iter([1, 2, 3, 4])
for x, y in izip(it, it):
    print x, y

Output:

1 2
3 4
>>> 
Nick Dandoulakis
  • 42,588
  • 16
  • 104
  • 136
  • 3
    Never thought of using a single iterator twice to zip... that's slick. For the finishing touch you'd want to use `from itertools import izip` to avoid making an extra copy. – Steve Losh Oct 29 '09 at 18:41
  • 4
    One more change: `zip(*[iter(the_list)]*2)` (or `*3` for 3-tuples, etc). – Steve Losh Oct 29 '09 at 18:44
7

Building on Nick D's answer:

>>> from itertools import izip
>>> t = [1,2,3,4,5,6,7,8,9,10,11,12]
>>> for a, b in izip(*[iter(t)]*2):
...     print a, b
...
1 2
3 4
5 6
7 8
9 10
11 12
>>> for a, b, c in izip(*[iter(t)]*3):
...     print a, b, c
...
1 2 3
4 5 6
7 8 9
10 11 12
>>> for a, b, c, d in izip(*[iter(t)]*4):
...     print a, b, c, d
...
1 2 3 4
5 6 7 8
9 10 11 12
>>> for a, b, c, d, e, f in izip(*[iter(t)]*6):
...     print a, b, c, d, e, f
...
1 2 3 4 5 6
7 8 9 10 11 12
>>>

Not quite as readable, but it shows a compact way to get any size tuple you want.

Steve Losh
  • 19,642
  • 2
  • 51
  • 44
5

Kind of easy with python's slicing operator:

l2 = zip(l1[0::2], l1[1::2])
Michael
  • 8,920
  • 3
  • 38
  • 56
2

Take a look at grouper function from itertools docs.

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)

In your case use it like this:

l1 = [1,2,3,4,5,6,7,8]
for (x, y) in grouper(2, l1):
    draw_thing(x, y)
Daniel Hernik
  • 321
  • 1
  • 3
  • 1
    Essentially just a long-hand version of what Steve Losh wrote. – ephemient Oct 29 '09 at 19:07
  • 1
    Right, I didn't saw his answer. But it's not exactly the same. This version may be usefull, when lenght of the list isn't dividable by amount of items you want to process in the loop. – Daniel Hernik Oct 29 '09 at 19:33
  • +1 I like this version, it's clearer, works with other lengths as you said, and is already on the docs. – nosklo Oct 30 '09 at 01:04
0

You can do:

l2 = []
for y in range(0, len(l1), 2):
    l2.append((l1[y], l1[y+1]))

I'm not doing any checks to make sure l1 has an even number of entries and such-like.

Dana
  • 32,083
  • 17
  • 62
  • 73
0

Not the most elegant solution

l2 = [(l1[i], l1[i+1]) for i in xrange(0,len(l1),2)]
shylent
  • 10,076
  • 6
  • 38
  • 55
0

No need to construct a new list. You can just iterate over the list by steps of 2 instead of 1. I use len(L) - 1 as the upper-bound so you ensure that you don't try to access past the end of the list.

for i in range(0, len(L) - 1, 2):
    draw_thing(L[i], L[i + 1])
jamessan
  • 41,569
  • 8
  • 85
  • 85
0
 list = [1,2,3,4,5,6]
 it = iter(list)
 newlist = [(x, y) for x, y in zip(it, it)] 
Tendayi Mawushe
  • 25,562
  • 6
  • 51
  • 57
  • You're iterating over (and unpacking) the tuples returned by `zip` to create a list of identical tuples. In Python 2 the list comprehension is superfluous, and in Python 3 you can just call `list`. – Stephan202 Oct 29 '09 at 19:35
-3

What's wrong with just accessing the correct index and incrementing?

for (int i=0;i<myList.Length;i++)
{
  draw_thing(myList[i],myList[++i]);
}

Oops - sorry, in C# mode. I'm sure you get the idea.

Wim
  • 11,998
  • 1
  • 34
  • 57