1

I need to write a function which removes odd numbers from a list and square remaining even numbers.

I've tried something like this:

def modify_list(l):
    l1 = [i ** 2 for i in l if i % 2 == 0]
    return l1

but it creates a copy from a list that I've passed to a function, whereas I need to modify the passed list itself, so the following code would result:

id(l1) == id(l) # True

I've also tried to rewrite the code using remove method, but I couldn't figure out how to square remaining elements from passed list so it would return the same list (not its copy)

def modify_list(l):
    for element in l:
        if element % 2 != 0:
            l.remove(element)

Is it possible to change my code in order to return the same list object that I've passed, but without odd numbers and with squared even numbers?

GaryMBloom
  • 5,350
  • 1
  • 24
  • 32
  • Use list assignment? `l[i] = ...`? – rdas Nov 27 '21 at 19:00
  • 2
    Try using `lst[:] = ops on lst` – Daniel Hao Nov 27 '21 at 19:05
  • I disagree with the reason for closing this question, there are no answers related to how to remove elements from the list in-place in the link attached. I believe that this question was closed too hastily and that the person who closed it should have payed more attention. – Vinzent Nov 27 '21 at 19:16
  • An easy solution to this question would be to process the list in reverse order, popping the even numbers and assigning the squared value to the list index for the odd numbers. – GaryMBloom Nov 27 '21 at 19:18
  • 2
    @Vinzent - I think the slice assignment answers in the linked dupe are responsive - those modify the list in place. `l[:] = [i**2 for i in l if l % 2 == 0]` achieves the stated goal. Maybe room for expansion with techniques for working on a list that's sufficiently large that you'd prefer not making a temporary in-memory copy? – Peter DeGlopper Nov 27 '21 at 19:38
  • " whereas I need to modify the passed list itself" - in this case, please [follow Python convention](https://stackoverflow.com/questions/11205254/why-dont-list-operations-return-the-resulting-list) and return `None` (rather, don't explicitly `return`) rather than the modified list. – Karl Knechtel Nov 27 '21 at 19:41
  • @Vinzent The slice assignment mentioned by Daniel Hao above will do exactly what is required, and there are two answers at that other question which make use of this (in addition to any other answers of relevance). As such, I agreed that that question (found by another user) was a suitable duplicate. – alani Nov 27 '21 at 20:58

1 Answers1

-1
def modify_list(l):
    li = [i**2 for i in l if i % 0 == 0]
    for n,i in enumerate(li):
        l[n] = i
    return l

lists are mutable so a direct assignment works. 'li' is a new list so will have a different id.

InhirCode
  • 338
  • 1
  • 4
  • 5
  • Aside from the typo (`i % 0`), you are not changing the length of the list, even if the `if` evaluates False for some elements. – alani Nov 27 '21 at 19:15
  • yup - sorry about typo and yes also, the original unchanged elements remain so an extra step would be needed or better code?? – InhirCode Nov 27 '21 at 19:23