'Use list of lists created from orignal list to get remaining values as a list of lists

I have a list that was used to create a new list of lists (sub_lst1) and I want to use that sub_list1 to filter the remaining values in the list. And use those remaining values to create a new list of lists (sub_lst2).

I have provided a toy example below of the problem.

I have tried the following:

lst = ['f','f','a','g','h','a','b','g','h','a','h','d','a','b']

sub_lst1 = []
sub_lst2 = []

>>> for i, v in enumerate(lst):
...     if "b" in v:
...             sub_lst1.append(lst[i-3:i+1])

>>>print(sub_lst1)
[['g', 'h', 'a', 'b'], ['h', 'd', 'a', 'b']]

>>> for i, v in enumerate(lst):
...     if sub_lst1[0:][0:] not in v:
...             sub_lst2.append(lst[i-2:i+1])
>>> print(sub_lst2)
[[], [], ['f', 'f', 'a'],['f', 'a', 'g'], ['a', 'g', 'h'], ['g', 'h', 'a'], ['a', 'b', 'g'], ['b', 'g', 'h'], ['g', 'h', 'a'], ['h', 'a', 'h'], ['a', 'h', 'd'], ['h', 'd', 'a']]

But the desired result would be to have the two sub-lists where one sub-list has the two preceding values to 'a' and 'b' and the second sub-list has the two preceding values of 'a' where 'b' does not follow 'a'. The sub-lists would look as follows:

>>> print(sub_lst1)
[['g', 'h', 'a', 'b'], ['h', 'd', 'a', 'b']]

>>> print(sub_lst2)
[['f', 'f', 'a'], ['g', 'h', 'a']]


Solution 1:[1]

I'd recommend tackling this problem by simply finding where the 'b's are and then slicing up the main list in one go, rather than doing it in two steps. For example:

lst = ['f','f','a','g','h','a','b','g','h','a','h','d','a','b']

sub_lst1 = []
sub_lst2 = []

to_find = 'b'
found_indexes = []

for i, v in enumerate(lst):
    if v == to_find:
        found_indexes.append(i)

last_idx = -1
for idx in found_indexes:
    sub_lst2.append(lst[last_idx+1:idx-3])
    sub_lst1.append(lst[idx-3:idx+1])
    last_idx = idx
if lst[-1] != to_find:  # don't forget to check in case 'b' isn't the last entry
    sub_lst2.append(lst[last_idx+1:])

This gets the result you are looking for, assuming that if 'b' isn't the last entry, you would want sub_lst2 to include the trailing letters.

I'm sure there's a solution with superior speed that involves turning the first lst into a single string of characters and then split()ing it using 'b', but I don't think speed is your concern and this answer will work for a list with contents of any type, not just single characters.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1