20
votes

I want to replace a sub-list from list a, with another sub-list. Something like this:

a=[1,3,5,10,13]

Lets say I want to take a sublist like:

a_sub=[3,5,10]

and replace it with

b_sub=[9,7]

so the final result will be

print(a) 
>>> [1,9,7,13]

Any suggestions?

4
I havent tried anything, because i have no idea how to do it. I have been searching on stackoverflow for about 2 hours for ideas. - darxyde
Do you know the position of a_sub in a? Will a_sub always be in a? - sloth
I don't know the position of a_sub in a, and a_sub will always be in a. - darxyde

4 Answers

18
votes
In [39]: a=[1,3,5,10,13]

In [40]: sub_list_start = 1

In [41]: sub_list_end = 3

In [42]: a[sub_list_start : sub_list_end+1] = [9,7]

In [43]: a
Out[43]: [1, 9, 7, 13]

Hope that helps

15
votes

You can do this nicely with list slicing:

>>> a=[1, 3, 5, 10, 13]
>>> a[1:4] = [9, 7]
>>> a
[1, 9, 7, 13]

So how do we get the indices here? Well, let's start by finding the first one. We scan item by item until we find a matching sublist, and return the start and end of that sublist.

def find_first_sublist(seq, sublist, start=0):
    length = len(sublist)
    for index in range(start, len(seq)):
        if seq[index:index+length] == sublist:
            return index, index+length

We can now do our replacement - we start at the beginning, replace the first one we find, and then try to find another after our newly finished replacement. We repeat this until we can no longer find sublists to replace.

def replace_sublist(seq, sublist, replacement):
    length = len(replacement)
    index = 0
    for start, end in iter(lambda: find_first_sublist(seq, sublist, index), None):
        seq[start:end] = replacement
        index = start + length

Which we can use nicely:

>>> a=[1, 3, 5, 10, 13]
>>> replace_sublist(a, [3, 5, 10], [9, 7])
>>> a
[1, 9, 7, 13]
1
votes

You need to take a slice from start_index to end_index + 1, and assign your sublist to it.

Just like you can do: - a[0] = 5, you can similarly assign a sublist to your slice: - a[0:5] -> Creates a slice from index 0 to index 4

All you need is to find out the position of the sublist you want to substitute.

>>> a=[1,3,5,10,13]

>>> b_sub = [9, 7]

>>> a[1:4] = [9,7]  # Substitute `slice` from 1 to 3 with the given list

>>> a
[1, 9, 7, 13]
>>> 

As you can see that, substituted sublist don't have to be of same length of the substituting sublist.

In fact you can replace, 4 length list with 2 length list and vice-versa.

0
votes

Here is another way to do this. This method works if we need to replaces more than one sublist:

a=[1,3,5,10,13]
a_sub=[3,5,10]
b_sub=[9,7]

def replace_sub(a, a_sub, b_sub):
    a_str = ',' + ','.join(map(str, a)) + ','
    a_sub_str = ',' + ','.join(map(str, a_sub)) + ','
    b_sub_str = ',' + ','.join(map(str, b_sub)) +','

    replaced_str = a_str.replace(a_sub_str, b_sub_str)[1 : -1]

    return map(int, replaced_str.split(','))

Result:

>>> replace_sub(a, a_sub, b_sub)
[1, 9, 7, 13]
>>> replace_sub([10, 13, 4], [3, 4], [7])
[10, 13, 4] #[3,4] is not in the list so nothing happens

Replace more than one sublist:

>>> a=[1,3,5,10,13,3,5,10]
>>> a_sub=[3,5,10]
>>> b_sub=[9,7]
>>> replace_sub(a, a_sub, b_sub)
[1, 9, 7, 13, 9, 7]