17

I'd like to split a comma separated value into pairs:

>>> s = '0,1,2,3,4,5,6,7,8,9'
>>> pairs = # something pythonic
>>> pairs
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]

What would # something pythonic look like?

How would you detect and handle a string with an odd set of numbers?

jsamsa
  • 939
  • 7
  • 12
  • possible duplicate of [How do you split a list into evenly sized chunks in Python?](http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python) – tzot Feb 27 '11 at 22:12

5 Answers5

44

Something like:

zip(t[::2], t[1::2])

Full example:

>>> s = ','.join(str(i) for i in range(10))
>>> s
'0,1,2,3,4,5,6,7,8,9'
>>> t = [int(i) for i in s.split(',')]
>>> t
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> p = zip(t[::2], t[1::2])
>>> p
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]
>>>

If the number of items is odd, the last element will be ignored. Only complete pairs will be included.

FogleBird
  • 74,300
  • 25
  • 125
  • 131
8

How about this:

>>> x = '0,1,2,3,4,5,6,7,8,9'.split(',')
>>> def chunker(seq, size):
...     return (tuple(seq[pos:pos + size]) for pos in xrange(0, len(seq), size))
...
>>> list(chunker(x, 2))
[('0', '1'), ('2', '3'), ('4', '5'), ('6', '7'), ('8', '9')]

This will also nicely handle uneven amounts:

>>> x = '0,1,2,3,4,5,6,7,8,9,10'.split(',')
>>> list(chunker(x, 2))
[('0', '1'), ('2', '3'), ('4', '5'), ('6', '7'), ('8', '9'), ('10',)]

P.S. I had this code stashed away and I just realized where I got it from. There's two very similar questions in stackoverflow about this:

There's also this gem from the Recipes section of itertools:

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)
Community
  • 1
  • 1
Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
8

A more general option, that also works on iterators and allows for combining any number of items:

 def n_wise(seq, n):
     return zip(*([iter(seq)]*n))

Replace zip with itertools.izip if you want to get a lazy iterator instead of a list.

Ants Aasma
  • 53,288
  • 15
  • 90
  • 97
4

A solution much like FogleBirds, but using an iterator (a generator expression) instead of list comprehension.

s = '0,1,2,3,4,5,6,7,8,9'
# generator expression creating an iterator yielding numbers
iterator = (int(i) for i in s.split(','))

# use zip to create pairs
# (will ignore last item if odd number of items)
# Note that zip() returns a list in Python 2.x, 
# in Python 3 it returns an iterator
pairs = zip(iterator, iterator)

Both list comprehensions and generator expressions would probably be considered quite "pythonic".

Johan
  • 1,292
  • 1
  • 13
  • 15
2

This will ignore the last number in an odd list:

n = [int(x) for x in s.split(',')]
print zip(n[::2], n[1::2])

This will pad the shorter list by 0 in an odd list:

import itertools
n = [int(x) for x in s.split(',')]
print list(itertools.izip_longest(n[::2], n[1::2], fillvalue=0))

izip_longest is available in Python 2.6.

Ayman Hourieh
  • 132,184
  • 23
  • 144
  • 116