0

I have a list s which looks as below:

s = [1, 2, 3]

I am replacing slice of 's' using below code:

s[1:4] = [22, 3, 4, 5, 6, 7]
print(s)

Output: [1, 22, 3, 4, 5, 6, 7]

My understanding s[1:4] should replace only 3 elements starting from 1st element and up to but not including 4th element.

Assumed Output: [1, 22, 3, 4]

meallhour
  • 13,921
  • 21
  • 60
  • 117
  • 1
    And your understanding is exactly what is happening, so where exactly do you see a problem? You know that indexing starts at `0`, right? Also, any slice that goes over the end of the list stops at the end. So, as expected, 2 and 3 get replaced by 22 and so on. – Thierry Lathuille Mar 20 '22 at 19:09
  • if `s = [1,2,3]` then `s[1]` returns `2` since python uses 0-indexed lists – Krokodil Mar 20 '22 at 19:11
  • In order to get the functionality that it sounds like you desire, you would have to do something like `b,e=1,4; s[b:e] = [22,3,4,5,6,7][0:(e-b)]` (provided `e >= b`) – bittahProfessional Mar 20 '22 at 19:30
  • "My understanding s[1:4] should replace only 3 elements " that is not correct. The number of elements replaced is **not determined by the size of the slice** but by the iterable you are using in the slice-assignment. – juanpa.arrivillaga Mar 20 '22 at 20:03

2 Answers2

5

So let's use a better example. I've included the output as commented out code in the code snippets

s = list(range(1, 11))
print(f"Len = {len(s)} | S = {s}")

# Len = 10 | S = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

There are 3 scenarios:

Case 1: Assigned list is shorter than the index range

s = list(range(1, 11))
s[1:4] = [0, 0]
print(f"Len = {len(s)} | S = {s}")

# Len = 9 | S = [1, 0, 0, 5, 6, 7, 8, 9, 10]

Ans : The list size is shrunk by 1 since only 2 items are being assigned to 3 places.

Case 2: Assigned list is longer than the index range

s = list(range(1, 11))
s[1:4] = [0, 0, 0, 0, 0, 0, 0]
print(f"Len = {len(s)} | S = {s}")

# Len = 14 | S = [1, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10]

Ans : The list size is increased by 4 since 7 items are being assigned to 3 places.

Case 3: Assigned list is equal to index range

s = list(range(1, 11))
s[1:4] = [0, 0, 0]
print(f"Len = {len(s)} | S = {s}")

# Len = 10 | S = [1, 0, 0, 0, 5, 6, 7, 8, 9, 10]

Ans : In this case it will be replaced properly since both the sizes match.

Conclusion

  • Python seems to be shrinking and growing the list to accommodate the assigned items.
  • All elements outside the slice indices will not be affected regardless of how big/small the assigned list is.

Update

As @mealhour pointed out there is a fourth case where you can increase the step size to be greater than 1 and assign it to every kth item in the list. In this case, the sizes have to match otherwise, python throws an error. This StackOverflow question explains it really well

s = list(range(1, 11))
# s[1:4:2] = [0, 0, 0] <- This throws an error
s[1:4:2] = [0, 0]
print(f"Len = {len(s)} | S = {s}")

# Len = 10 | S = [1, 0, 3, 0, 5, 6, 7, 8, 9, 10]
DollarAkshay
  • 2,063
  • 1
  • 21
  • 39
  • Why are you using `np.arange` here? just change it to `range` – juanpa.arrivillaga Mar 20 '22 at 20:04
  • @juanpa.arrivillaga I wasn't aware you could convert the `range()` generator into a list. Nice to know :) I have updated my answer – DollarAkshay Mar 20 '22 at 20:18
  • 2
    @DollarAkshay of course you can. Note, you can convert *any* iterable to a list, generators are iterable. But also note, `range` is not a generator – juanpa.arrivillaga Mar 20 '22 at 21:11
  • @DollarAkshay thanks for the insights. can you please also provide case example on how `assignment to extended slice` works? How `s[1:4:2] = [0, 0, 0]` will work? – meallhour Mar 20 '22 at 21:31
  • @DollarAkshay thanks again. I have also created another question for it and want to request you to please help answer it. https://stackoverflow.com/questions/71550868/replacing-extended-slice-of-a-list-with-another-list?noredirect=1#comment126459337_71550868 – meallhour Mar 20 '22 at 21:49
1
s = [1,2,3]
x = [22,3,4,5,6]
j = 0
for i in range(1,4):
    try:
        s[i] = x[j]
    except IndexError:
        s.append(x[j])
    j +=1

You can use something like this to achieve your goal

Sajjad Zaidi
  • 159
  • 1
  • 10