NarūnasK
NarūnasK

Reputation: 4950

How to slice Python list by the occurrences of an item?

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

Answers (2)

RoadRunner
RoadRunner

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

tobias_k
tobias_k

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

Related Questions