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?
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']]
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']]
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'
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 [[]]
.
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']]
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)
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:]
)
You can try using the snippet below. Use more_itertools
>>> l = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
>>> from more_itertools import sliced
>>> list(sliced(l,l.index('c')+1))
Output:
[['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]