Felix Felix - 1 year ago 66
Python Question

Splitting a list into uneven tuples

I'm trying to split a list of strings into a list of tuples of uneven length containing these strings, with each tuple containing strings initially separated with blank strings. Basically I'd need the parameterized split that I could apply to lists. If my initial list looks like:

init = ['a', 'b', '', 'c', 'd e', 'fgh', '', 'ij', '', '', 'k', 'l', '']

The last element of this list is always a closing
. There can be consecutive
s which shall be considered as singles.
The result I need is:

end = [('a', 'b'), ('c', 'd e', 'fgh'), ('ij',), ('k', 'l')]

I already have ugly code that does the job and gets out of range once the list is fully popped out:

end = []
while init[-1] == u'':
l = []
while init[-1] != u'':

I'd like to use comprehensions, but having unsuccessfully tried unpacking argument lists, reversing self-referenced lists, using
queues, and various code smells, I'm now doubting whether it makes sense looking for a (nested) comprehension solution?

Answer Source

You can use itertools.groupby function to group the elements based on their sizes, like this

>>> from itertools import groupby
>>> init = ['a', 'b', '', 'c', 'd e', 'fgh', '', 'ij', '', '', 'k', 'l', '']
>>> [tuple(g) for valid, g in groupby(init, key=lambda x: len(x) != 0) if valid]
[('a', 'b'), ('c', 'd e', 'fgh'), ('ij',), ('k', 'l')]

This basically groups the elements based on their lengths. If the length of the item is not equal to zero, they will be put in a group, till an element from another group is met. The key function would return True for the group of elements whose length is not equal to zero, False otherwise. We ignore the group with False (hence the check if valid).