FAQ: Code Challenge: Lists - Remove Middle

Solution using pop()

def remove_middle(lst, start, end):
  for i in range(start,end+1):
    lst.pop(start)
  return lst

4 posts were split to a new topic: Can I use - on lists (subtract) [code challenge lists]

Am I the only one who didn’t understand what the heck the instructions were saying on this task or the previous one?

6 Likes

Since the instructions are asking to remove a sequential slice, I simply assigned the parameter slice as an empty list to remove it.

def remove_middle(lst, start, end):
  lst[start:end+1] = []
  return lst
4 Likes

This also makes sense, and doesn’t need +1 in the slice…

>>> def remove_middle(lst, start, end):
  lst[start:end] = []
  return lst

>>> remove_middle([1, 2, 3, 4, 5, 6, 7, 8, 9], 3, 6)
[1, 2, 3, 7, 8, 9]
>>> 

I believe @appylpye once explored this method. As simple as it is, it rarely comes first to mind for most learners.

2 Likes

Yes, the post is here.

1 Like

As an experiment, in the function
def remove_middle(lst, start, end):
return lst[:start] + lst[end+1:]
I set the argument “end” equal to 10 being aware of course that in the given line
print(remove_middle([4, 8, 15, 16, 23, 42], 1, 10))
there is not index 10 or as the functions defines 11 (end+1)

I expected that an error would come up and the code would not be executed. I was driven to this thought by recalling the previous exercise 2. (“Double Index”) where the statement
if index >= len(lst) was necessary otherwise an indexerror would occur (“index out of range”).

Nevertheless, unexpectedly, the code was normally executed and the output was [4].
I suspect, the part lst[end+1:] -> lst[11:] was calculated as to be an empty list i.e lst [ ] although no such input/constraint was given in the function.

Why didn’t an index error occur as long as index 11 does not exist? How does the concept of this exercise differs from the previous in terms of ‘out of range index’ ?
Shouldn’t it be better for the sake of precision to add in this remove_middle function an if statement in order to define the limits of index range?

List slices containing a colon will not raise an error. Slices are separate entities from the actual list being sliced. They take what is given to them, whether nothing or not. The behavior you are witnessing is normal and to be expected.

>>> a = []
>>> a[0]
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    a[0]
IndexError: list index out of range
>>> a[0:]
[]
>>> 
1 Like

Am I wrong or is it realy impossible to write the code that removes elements between two other if we are given only the indices? (at least without any knowledge outside the course) As start and end are parameters, they can be any integer. What about the situation when any of them are negative, or both, or start greater than end, or any of them is out of the range of list while being negative?.. I tried to define elifs for all possible situations, but the code seems too hard =D By the way, the task is concidered to be solved even if you write the function for the only situation: start > 0 and start < end, but it kinda wrong…

We should be able to work with just indices to make this work, but the function is most useful if we supply a list rather than mutate a global. We can set out criteria to test the inputs against.

First check if the indices are both in range. Given a list, and two indices,

def in_range(lst, x):
    return -len(lst) <= x < len(lst)

if in_range(lst, start) and in_range(lst, end):
    if end < start:
       start, end = end, start  # => swap two indices

This permits negative indices which are valid.

def remove_middle(lst, start, end):
return lst[:start] + lst[-end + 1:]
This took an embarrassing amount of time to solve, and I still feel like I stumbled on the solution completely by accident,

1 Like

The solution I came up with totally not using the slice mechanisms in Python. But it works.

def remove_middle(lst, start, end):
  output_list = []
  for i in range(len(lst)):
    if i < start or i > end:
      output_list.append(lst[i])
  return output_list

Is using the del statement a valid method? I found out about it after getting stuck and finally found a way that seems to work.

#Write your function here
def remove_middle(lst, start,end):
  del lst[start:end+1]
  return lst

#Uncomment the line below when your function is done
print(remove_middle([4, 8, 15, 16, 23, 42], 2, 4))

Hey, group…I too am a beginner at programming and was wondering why my strategy I came up with is throwing a TypeError: int() can’t convert non-string with explicit base in the interpreter.

This is my code in the IDE is as follows:

#Write your function here
def remove_middle(lst, start, end):
if start <= end <= len(lst):
lst = lst.pop(range(int(start, end)));
return lst
else:
return lst

#Uncomment the line below when your function is done
print(remove_middle([4, 8, 15, 16, 23, 42], 1, 3))

The output on the interpreter is as follows:
Traceback (most recent call last):
File “script.py”, line 10, in
print(remove_middle([4, 8, 15, 16, 23, 42], 1, 3))
File “script.py”, line 4, in remove_middle
lst = lst.pop(range(int(start, end)));
TypeError: int() can’t convert non-string with explicit base

>>> int('0xFF', 16)
255
>>> 

Notice how the first argument is type str, and the second describes the number base the string represents?

Ohhhhh…you have to tell the interpreter what number base you wish the string to be converted! Duh

Okay so I got that concept…now…can the int function be used with a combination of arguements at once…ie 2 numbers at the same time in one line of code? Here is what I came up with and its shooting out errors like crazy.

def remove_middle(lst, start, end):
  if start <= end <= len(lst):
    lst = lst.pop(range(int('start', 10), int('end', 10)));
    return lst
  else:
    return lst

Interpreter displaying this error:

Traceback (most recent call last):
  File "script.py", line 10, in <module>
    print(remove_middle([4, 8, 15, 16, 23, 42], 1, 3))
  File "script.py", line 4, in remove_middle
    lst = lst.pop(range(int('start', 10), int('end', 10)));
ValueError: invalid literal for int() with base 10: 'start'

AFAIK, pop() can only take one integer argument (an index) at a time, not a range or list.

The first argument can be a number or a string, the second argument is always a number, the base. int() is a constructor, so the arguments are positionally based.

I like how you put it. Interesting…hmmm, well I came up with this strategy and it seems to execute up to the first return in the interpreter then throws a return syntax which I cannot seem to grasp.

Below is the code in the IDE:

#Write your function here
def remove_middle(lst, start, end):
  if start <= end <= len(lst):
    lst = lst.pop(range(int(bin(start), 2), int(bin(end), 2))
      return lst
  else:
    return lst

#Uncomment the line below when your function is done
print(remove_middle([4, 8, 15, 16, 23, 42], 1, 3))

And this is the result in the interpreter:

File "script.py", line 5
    return lst
         ^
SyntaxError: invalid syntax

The error is because of indentation in the block above that line. Since it is a syntax error it didn’t have a chance to actually run the code or we would get this exception…

TypeError: 'range' object cannot be interpreted as an integer

As mentioned earlier, pop takes an integer, not a sequence.

Hi, I’m trying to use this solution:

def remove_middle (lst, start, end):
lst1=lst[:start]
lst2=lst[end:]+1
return lst1+lst2

But I’m getting “can only concatenate list (not “int”) to list” error. What am I doing wrong?