0

I've written a code that simply takes a few commands from the standard input and tries to modify a list based on the commands. The user can pop the last element of the list, insert a new value, append, sort the list, and so on. The problem I am facing, is that the code modifies the list and prints the FINAL result after going through ALL the commands. But I want the list modification printed precisely for EACH command one after another!

Here's my code:

import re

lst = [5,1,6,2,6,2,9,12,1,5]

def insert_element(index, value, lst):
    lst.insert(index, value)
    return lst

def remove_element(element, lst):
    lst.remove(element)
    return lst

def append_element(value, lst):
    lst.append(value)
    return lst

def sort_list(lst):
    lst = sorted(lst)
    return lst

def pop_element(lst):
    lst.pop()
    return lst

def reverse_list(lst):
    lst = lst[::-1]
    return lst


commands = []
results = []

queries = int(input())

for i in range(queries):
    commands.append(input())

for j in commands:
    if re.match(r'insert*', j):
        results.append(insert_element(int(j[7]), int(j[9]), lst))
    
    if re.match(r'remove*', j):
        results.append(remove_element(int(j[7::]), lst))

    if re.match(r'append*', j):
        results.append(append_element(int(j[7::]), lst))

    if re.match(r'sort*', j):
        results.append(sort_list(lst))

    if re.match(r'pop*', j):
        results.append(pop_element(lst))

    if re.match(r'reverse*', j):
        results.append(reverse_list(lst))

    if re.match(r'print*', j):
        results.append(lst)

for z in results:
    print(z)

SAMPLE INPUT

4
print
pop
append 3
insert 2 9

EXPECTED OUTPUT

[5,1,6,2,6,2,9,12,1,5]
[5,1,6,2,6,2,9,12,1]
[5,1,6,2,6,2,9,12,1,3]
[5,1,5,6,2,6,2,9,12,1,3]

CODE'S OUTPUT

[5,1,5,6,2,6,2,9,12,1,3]
[5,1,5,6,2,6,2,9,12,1,3]
[5,1,5,6,2,6,2,9,12,1,3]
[5,1,5,6,2,6,2,9,12,1,3]

How can I make it get the expected output rather than this?! I really appreciate any help.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Liana
  • 314
  • 5
  • 15
  • "The problem I am facing, is that the code modifies the list and prints the FINAL result after going through ALL the commands. But I want the list modification printed precisely for EACH command one after another!" Okay, so. What's the thing you did in your code that causes the list to be printed? What happened when you tried... doing that, at the points in the code where you want it to happen? I don't understand what the actual difficulty is here. – Karl Knechtel Apr 09 '21 at 11:07
  • Ah, I see now how you intend for the program to be structured. In this case, the problem is the same as in https://stackoverflow.com/questions/240178/list-of-lists-changes-reflected-across-sublists-unexpectedly . – Karl Knechtel Apr 09 '21 at 11:08

3 Answers3

1

The problem here is that you're modifying the same list object lst and then adding it back into your list results. The functions you apply all operate "in-place" meaning the modify the list, rather than making a copy first. The solution is to copy the list yourself before you supply it to your own functions, or modify your functions to copy the list before you operate on it. This can be done with lst.copy().

So either, e.g,

results.append(insert_element(int(j[7]), int(j[9]), lst.copy()))

or,

def insert_element(index, value, lst):
    lst_copy = lst.copy()
    lst_copy.insert(index, value)
    return lst_copy

PS: I don't think the other answer will quite work, as it copies the list after it has already been modified in-place.

Jared
  • 86
  • 7
1

All of the operations you are performing except for reversing the list are changing the mutable object lst; therefore, you are really just changing the same object multiple times. So your results list just contains pointers to the same object, which is why you are getting the same output (notice how it is the same as the last line in your expected output). If you really want to store the state of the list after each command, you can append a copy of it to results using the copy (https://docs.python.org/3/library/copy.html) module. Otherwise, you can print the list within the loop over the commands.

Lucas Ford
  • 181
  • 3
0

you should copy the list before appending it to result, like

change

    if re.match(r'print*', j):
        results.append(lst)

to

    if re.match(r'print*', j):
        results.append(lst[:])
lidaobing
  • 1,005
  • 13
  • 26