mb567
mb567

Reputation: 681

Split list at a specific value

I am trying to write a code that splits lists in a class of lists in two when a certain value is a middle element of the list and then produce two lists where the middle element becomes the end element in the first list and the first element in the second one.

There can be more than n middle elements in the list so the result must be n+1 lists.

Example:

A = [[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[16,17,18,19,20,21,22,23,24,25],[26,27,28,29]]

P = [4,7,13,20]
n = len(Points) # in this case n = 4

I am looking for a result that looks like this:

A = [[0,1,2,3,4],[4,5,6,7],[7,8,9,10,11,12,13],[13,14,15],[16,17,18,19,20],[20,21,22,23,24,25],[26,27,28,29]]

Since n = 4 and it will produce 5 lists, note that the answer has 6 lists because the last list doesn't have any value of P in and therefore stays intact.

I haven't been able to produce anything as I am new to python and it is hard to formulate this problem.

Any help is appreciated!

Upvotes: 1

Views: 6541

Answers (2)

Olivier Melançon
Olivier Melançon

Reputation: 22294

You can first recover all indices of the provided values and then slice accordingly.

Code

def split_at_values(lst, values):
    indices = [i for i, x in enumerate(lst) if x in values]
    for start, end in zip([0, *indices], [*indices, len(lst)]):
        yield lst[start:end+1]
        # Note: remove +1 for separator to only appear in right side slice

Example

values =  {4, 7, 13, 20}
lst = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]

print(*split_at_values(lst, values))

Output

[0, 1, 2, 3, 4] [4, 5, 6, 7] [7, 8, 9, 10, 11, 12, 13] [13, 14, 15]

You can then apply this iteratively to you input list A to get the desired result. Alternatively you can use itertools.chain.from_iterable.

from itertools import chain

values = {4, 7, 13, 20}
lst_A = [[0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
         [16, 17, 18, 19, 20, 21, 22, 23, 24, 25],
         [26, 27, 28, 29]]

output = list(chain.from_iterable(split_at_values(sublst, values) for sublst in lst_A))

print(output)

Output

[[0, 1, 2, 3, 4],
 [4, 5, 6, 7],
 [7, 8, 9, 10, 11, 12, 13],
 [13, 14, 15],
 [16, 17, 18, 19, 20],
 [20, 21, 22, 23, 24, 25],
 [26, 27, 28, 29]]

Upvotes: 4

blhsing
blhsing

Reputation: 106445

You can keep appending the sub-list items to the last sub-list of the output list, and if the current item is equal to the next item in Points, append a new sub-list to the output with the same item and pop the item from Points:

output = []
for l in List:
    output.append([])
    for i in l:
        output[-1].append(i)
        if Points and i == Points[0]:
            output.append([i])
            Points.pop(0)

With your sample input, output would become:

[[0, 1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10, 11, 12, 13], [13, 14, 15], [16, 17, 18, 19, 20], [20, 21, 22, 23, 24, 25], [26, 27, 28, 29]]

Upvotes: 0

Related Questions