3

I just extracted some data from a list using python but think it's overcomplicated and unpythonic and there's probably a much better way to do this. I'm actually pretty sure I saw this somewhere in the standard library docs but my brain refuses to tell me where.

So here it goes:

Input:

x = range(8) # any even sequence

Output:

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

My take:

[ [x[i], x[i+1]] for i in range(len(x))[::2] ]
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
c089
  • 4,951
  • 2
  • 25
  • 37
  • You say two-tuples but your examples are "two-lists" – Ben Jackson May 15 '11 at 10:14
  • 1
    duplicated (a lot of times): http://stackoverflow.com/questions/434287/what-is-the-most-pythonic-way-to-iterate-over-a-list-in-chunks – tokland May 15 '11 at 10:15
  • Oops, of course, sorry for the mixup. Doesn't really matter for the question though ;) – c089 May 15 '11 at 10:28
  • I think it does matter. Tuples are a lot simpler than lists, as demonstrated in [my answer](http://stackoverflow.com/questions/6007736/getting-two-tuples-out-of-a-list/6007963#6007963). – johnsyweb May 15 '11 at 11:19

4 Answers4

7

Tuples?

In Python 2.n

>>> zip(*2*[iter(x)])
[(0, 1), (2, 3), (4, 5), (6, 7)]

In Python 3.n

zip() behaves slightly differently...

>> zip(*2*[iter(x)])
<zip object at 0x285c582c>
>>> list(zip(*2*[iter(x)])])
[(0, 1), (2, 3), (4, 5), (6, 7)]

Lists?

The implementation is the same in Python 2 and 3...

>>> [[i,j] for i,j in zip(*2*[iter(x)])]
[[0, 1], [2, 3], [4, 5], [6, 7]]

Or, alternatively:

>>> [list(t) for t in zip(*2*[iter(x)])]
[[0, 1], [2, 3], [4, 5], [6, 7]]

The latter is more useful if you want to split into lists of 3 or more elements, without spelling it out, such as:

>>> [list(t) for t in zip(*4*[iter(x)])]
[[0, 1, 2, 3], [4, 5, 6, 7]]

If zip(*2*[iter(x)]) looks a little odd to you (and it did to me the first time I saw it!), take a look at How does zip(*[iter(s)]*n) work in Python?.

See also this pairwise implementation, which I think is pretty neat.

Community
  • 1
  • 1
johnsyweb
  • 136,902
  • 23
  • 188
  • 247
  • This is actually really elegant (but a little hard to read). Thanks for all answers, learned a lot :) – c089 May 15 '11 at 13:46
  • I find `zip(*[iter(s)]*n)` quite ugly, but the idiom is in [the documentation](http://docs.python.org/library/functions.html#zip), so I guess it's Pythonic. For pairs, I like the `pairwise()` version to which I linked. [Beautiful is better than ugly](http://www.python.org/dev/peps/pep-0020/), right? – johnsyweb May 15 '11 at 21:43
1

If you want tuples instead of lists you can try:

>>> zip(range(0, 8, 2), range(1, 8, 2))
[(0, 1), (2, 3), (4, 5), (6, 7)]
Mariy
  • 5,746
  • 4
  • 40
  • 57
1

Input:

x = range(8) # any even sequence

Solution:

output = []
for i, j in zip(*[iter(x)]*2):
    output.append( [i, j] )

Output:

print output
[[0, 1], [2, 3], [4, 5], [6, 7]]
gsbabil
  • 7,505
  • 3
  • 26
  • 28
0

You can rewrite it a bit:

>>> l = range(8)
>>> [[l[i], l[i+1]] for i in xrange(0, len(l), 2)]
[[0, 1], [2, 3], [4, 5], [6, 7]]

For some list tasks you can use itertools, but I'm pretty sure there's no helper function for this one.

AndiDog
  • 68,631
  • 21
  • 159
  • 205