Reputation: 8047
I have a list and I want to split it into parts moslty like str.split()
works for strings with the following differences:
True
for element of the list, this element is considered as a delimeter.For example:
split_by_predicate([0, "One", 1, 2, 3,
"Two", 4, 5, 6, 7, "Three", "Four"],
predicate=lambda x: isinstance(x, str))
should give me
[[0], ["One", 1, 2, 3], ["Two", 4, 5, 6, 7], ["Three"], ["Four"]]
I can write the following code:
def split_by_predicate(it, predicate):
lst = []
cur = []
for element in it:
if predicate(element):
lst.append(cur)
cur = []
cur.append(element)
lst.append(cur)
return lst
But I find it not elegant and not Pythonic. A similar approach is given here (using generators).
I tried to figure out some kind of itertools
-based solution like this one, but they don't work well if the delimeter is repeated (like in my example).
Are there any ideas how to do it in more functional style than my current code?
Upvotes: 1
Views: 86
Reputation: 1608
You can simplify your function to this:
def split_by_predicate(it, predicate):
lst = [[]]
for element in it:
if predicate(element):
lst.append([])
lst[-1].append(element)
return lst
Or this ( with skiped appending empty list on first iteration ):
def split_by_predicate(it, predicate):
lst = [[]]
for i, element in enumerate(it):
if predicate(element) and i:
lst.append([])
lst[-1].append(element)
return lst
Upvotes: 5
Reputation: 7055
What about this:
def split_by_predicate(it, predicate):
o = []
for i in it:
if predicate(i) or len(o) == 0:
o += [[i]]
else:
o[-1] += [i]
return o
Output:
>>> split_by_predicate([0, 'One', 1, 2, 3, 'Two', 4, 5, 6, 7, 'Three', 'Four'], lambda x: isinstance(x,str))
[[0], ['One', 1, 2, 3], ['Two', 4, 5, 6, 7], ['Three'], ['Four']]
Upvotes: 1