Reputation: 63
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'':
init.pop()
l = []
while init[-1] != u'':
l.append(init.pop())
end.append(tuple(l))
I'd like to use comprehensions, but having unsuccessfully tried unpacking argument lists, reversing self-referenced lists, using deque
queues, and various code smells, I'm now doubting whether it makes sense looking for a (nested) comprehension solution?
Upvotes: 6
Views: 443
Reputation: 107347
Here is a more concise and general approach with groupby
if you want to split your list with a special delimiter:
>>> delimiter = ''
>>> [tuple(g) for k, g in groupby(init, delimiter.__eq__) if not k]
[('a', 'b'), ('c', 'd e', 'fgh'), ('ij',), ('k', 'l')]
Upvotes: 4
Reputation: 239573
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
).
Upvotes: 4