12

What is the nicest way of splitting this:

tuple = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h')

into this:

tuples = [('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', 'h')]

Assuming that the input always has an even number of values.

Dan
  • 33,953
  • 24
  • 61
  • 87

5 Answers5

41

zip() is your friend:

t = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h')
zip(t[::2], t[1::2])
  • 1
    +1 because it's pretty and I didn't know about the [::] syntax – Steve B. Apr 16 '09 at 15:14
  • doesn't works for tuple = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i') # note the last 'i', that makes the tuples odd-length – dfa Apr 16 '09 at 17:12
  • @dfa: what do you mean it doesn't work? is it specified how new list should be formed in case of odd-length input? – SilentGhost Apr 16 '09 at 17:18
  • ops, I've just read: "Assuming that the input always has an even number of values." – dfa Apr 16 '09 at 17:21
  • @dfa: well if the input is has an odd number of elements, what should happen to the left over element? Should it be a one element tuple or should it be (x, None)? You have to massage you input according to the expected output. –  Apr 16 '09 at 17:35
15
[(tuple[a], tuple[a+1]) for a in range(0,len(tuple),2)]
Peter Hoffmann
  • 56,376
  • 15
  • 76
  • 59
6

Or, using itertools (see the recipe for grouper):

from itertools import izip
def group2(iterable):
   args = [iter(iterable)] * 2
   return izip(*args)

tuples = [ab for ab in group2(tuple)]
Andrew Jaffe
  • 26,554
  • 4
  • 50
  • 59
0

I present this code based on Peter Hoffmann's answer as a response to dfa's comment.

It is guaranteed to work whether or not your tuple has an even number of elements.

[(tup[i], tup[i+1]) for i in range(0, (len(tup)/2)*2, 2)]

The (len(tup)/2)*2 range parameter calculates the highest even number less or equal to the length of the tuple so it is guaranteed to work whether or not the tuple has an even number of elements.

The result of the method is going to be a list. This can be converted to tuples using the tuple() function.

Sample:

def inPairs(tup):
    return [(tup[i], tup[i+1]) for i in range(0, (len(tup)/2)*2, 2)]

# odd number of elements
print("Odd Set")
odd = range(5)
print(odd)
po = inPairs(odd)
print(po)

# even number of elements
print("Even Set")
even = range(4)
print(even)
pe = inPairs(even)
print(pe)

Output

Odd Set
[0, 1, 2, 3, 4]
[(0, 1), (2, 3)]
Even Set
[0, 1, 2, 3]
[(0, 1), (2, 3)]
Community
  • 1
  • 1
Alex Essilfie
  • 12,339
  • 9
  • 70
  • 108
-1

Here's a general recipe for any-size chunk, if it might not always be 2:

def chunk(seq, n):
    return [seq[i:i+n] for i in range(0, len(seq), n)]

chunks= chunk(tuples, 2)

Or, if you enjoy iterators:

def iterchunk(iterable, n):
    it= iter(iterable)
    while True:
        chunk= []
        try:
            for i in range(n):
                chunk.append(it.next())
        except StopIteration:
            break
        finally:
            if len(chunk)!=0:
                yield tuple(chunk)
bobince
  • 528,062
  • 107
  • 651
  • 834