Reputation: 4950
If given the following list lst
:
import random as rnd, operator as op, itertools as it
from functools import partial
lst = [x for x in it.islice(it.cycle(range(1,10)), 50)]
idx = set(rnd.sample(range(len(lst)), 10))
for i in idx:
lst.insert(i, 0)
How can I slice it by the occurrences of 0?
My current strategy is this:
new_lst = [list(g) for k,g in it.groupby(lst, partial(op.eq, 0))]
new_lst
[[1, 2, 3, 4],
[0],
[5, 6, 7, 8, 9],
[0],
[1, 2],
[0],
[3, 4],
[0],
[5],
[0],
[6, 7, 8],
[0],
[9, 1, 2, 3, 4, 5, 6, 7],
[0],
[8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[0],
[1, 2, 3, 4, 5, 6],
[0],
[7],
[0],
[8, 9, 1, 2, 3, 4, 5]]
Note in the resulting new_lst
I still have the separators, hence to achieve the desired result I have to iterate over once again:
new_lst = [i for i in new_lst if 0 not in i]
new_lst
[[1, 2, 3, 4],
[5, 6, 7, 8, 9],
[1, 2],
[3, 4],
[5],
[6, 7, 8],
[9, 1, 2, 3, 4, 5, 6, 7],
[8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6],
[7],
[8, 9, 1, 2, 3, 4, 5]]
Is there a more efficient way to do this?
Upvotes: 0
Views: 124
Reputation: 26325
You could also try this, which uses no libraries:
lst = [0, 1, 2, 3, 4, 0, 0, 5, 6, 0, 7, 8, 9, 10, 0, 0]
# indices of all zeroes
indexes = [-1] + [i for i, e in enumerate(lst) if e == 0]
# get all the sublists
result = []
for start, end in zip(indexes, indexes[1:]):
result.append(lst[start+1:end])
# add last if any
result.append(lst[end+1:])
# filter out empty lists
print([x for x in result if x])
Which Outputs:
[[1, 2, 3, 4], [5, 6], [7, 8, 9, 10]]
Upvotes: 0
Reputation: 82929
Just use a condition on the key, k
:
new_lst = [list(g) for k,g in it.groupby(lst, partial(op.eq, 0)) if not k]
Or more direct, using op.ne
:
new_lst = [list(g) for k,g in it.groupby(lst, partial(op.ne, 0)) if k]
Or without partial
(note the space in 0 .__ne__
, or use (0).__ne__
):
new_lst = [list(g) for k,g in it.groupby(lst, 0 .__ne__) if k]
Upvotes: 4