Split list by cost and keep separators
I have a list called list_of_strings
that looks like this:
['a', 'b', 'c', 'a', 'd', 'c', 'e']
I want to split this list by value (in this case c
). I also want to keep c
the resulting split.
So the expected output is:
[['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]]
Any easy way to do this?
source to share
You can use more_itertoools
to accomplish this simply and clearly:
from more_itertools import split_after
lst = ["a", "b", "c", "a", "d", "c", "e"]
list(split_after(lst, lambda x: x == "c"))
# [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
Another example: here we are splitting words by simply changing the predicate :
lst = ["ant", "bat", "cat", "asp", "dog", "carp", "eel"]
list(split_after(lst, lambda x: x.startswith("c")))
# [['ant', 'bat', 'cat'], ['asp', 'dog', 'carp'], ['eel']]
source to share
def spliter(value, array):
res = []
while value in array:
index = array.index(value)
res.append(array[:index + 1])
array = array[index + 1:]
if array:
# Append last elements
res.append(array)
return res
a = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
print(spliter('b',a))
# [['a', 'b'], ['c', 'a', 'd', 'c', 'e']]
print(spliter('c',a))
# [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
source to share
You can try something like the following:
list_of_strings = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
output = [[]]
for x in list_of_strings:
output[-1].append(x)
if x == 'c':
output.append([])
Although it should be noted that this will add an empty list to your output if your last input element is 'c'
source to share
How about this. It only needs to iterate over one input, and some of them are in a method index
that is executed as native code.
def splitkeep(v, c):
curr = 0
try:
nex = v.index(c)
while True:
yield v[curr: (nex + 1)]
curr = nex + 1
nex += v[curr:].index(c) + 1
except ValueError:
if v[curr:]: yield v[curr:]
print(list(splitkeep( ['a', 'b', 'c', 'a', 'd', 'c', 'e'], 'c')))
result
[['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
I was not sure if you wanted to keep an empty list at the end of the result if the final value was the value you split. I made the assumption that you won't, so I put the condition in a final value exception if it is empty.
This causes the input to []
only lead to []
, if possible, it can lead to [[]]
.
source to share
How about this rather playful script:
a = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
b = ''.join(a).split('c') # ['ab', 'ad', 'e']
c = [x + 'c' if i < len(b)-1 else x for i, x in enumerate(b)] # ['abc', 'adc', 'e']
d = [list(x) for x in c if x]
print(d) # [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
It can also handle start and end values ββwith "c"
a = ['c', 'a', 'b', 'c', 'a', 'd', 'c', 'e', 'c']
d -> [['c'], ['a', 'b', 'c'], ['a', 'd', 'c'], ['e', 'c']]
source to share
list_of_strings = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
value = 'c'
new_list = []
temp_list = []
for item in list_of_strings:
if item is value:
temp_list.append(item)
new_list.append(temp_list[:])
temp_list.clear()
else:
temp_list.append(item)
if (temp_list):
new_list.append(temp_list)
print(new_list)
source to share
stuff = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
You can find out the indices using 'c'
like this and add 1 because after that you will split it, not by its index:
indices = [i + 1 for i, x in enumerate(stuff) if x == 'c']
Then extract the snippets like this:
split_stuff = [stuff[i:j] for i, j in zip([0] + indices, indices + [None])]
zip
gives you a list of tuples, similar (indices[i], indices[i + 1])
, with the concatenated [0]
one allowing you to extract the first part and [None]
extract the last fragment ( stuff[i:]
)
source to share