-1

I'm trying to understand what the following function does, and in specific what does the if part is doing:

def remove(items, value):
    new_items = []
    found = False

    for item in items:
        if not found and item == value:  
            found = True
            continue
        new_items.append(item)
    if not found :
        raise ValueError('list.remove(x): x not in list')

    return new_items

The statement if not found and item == value: and the trick of variable found . can someone specifically explain it?


Thanks, Now I understand the example code snippet above. And I can write code to implement my idea

My idea is to first make sure the value is in the initial list . then compare every item with that value, add the item which doesn't satisfy condition item != value to a new list new_items, finally return the new list.

def remove(items, value):
    new_items = []
    for item in items:
        if item == value :
            continue
        else : 
            new_items.append(item)
        if len(items) == len(new_items):
            print("This value is not in the list")
    return new_items
ComplicatedPhenomenon
  • 4,055
  • 2
  • 18
  • 45
  • if you want to remove the value why do you want to add it to the initial list? your question is not clear – Nir Alfasi Oct 17 '17 at 02:04
  • 2
    Can you clarify the problem? Is it a lack of understanding? Incorrect behavior? You're saying what you want to do, and doing it correctly AFAICT, so what is the problem? Is this not your code, and you're trying to figure it out? – ShadowRanger Oct 17 '17 at 02:06
  • @alfasin I add the item which should not be deleted to a new list and return that new list. then it appear that I delete an item from the beginning list – ComplicatedPhenomenon Oct 17 '17 at 02:07
  • 1
    @alfasin this code seems to work (as described)... I think the question is "explain this line of 'my' code". – Andy Hayden Oct 17 '17 at 02:07
  • @ComplicatedPhenomenon if you have an item in the list and you call `remove` with that item - this code will remove it. I'm not sure I understand what you're asking... – Nir Alfasi Oct 17 '17 at 02:09
  • 1
    Further, this code will remove *only* the first item that is equal to the item that was sent to the function: if there are other copies of this item in the list - those copies will not be removed. Is that what confuses you? – Nir Alfasi Oct 17 '17 at 02:10
  • @I am trying to understand the specific implementation of that `remove` method – ComplicatedPhenomenon Oct 17 '17 at 02:11
  • @alfasin you are right, it's not a perfect example still. – ComplicatedPhenomenon Oct 17 '17 at 02:13
  • 2
    Have you tried creating sample data and writing down the algorithm on paper? – OneCricketeer Oct 17 '17 at 02:14
  • *then it appear that I delete an item from the beginning list*... That's not what this function does. The initial list is never modified – OneCricketeer Oct 17 '17 at 02:15
  • 2
    It sounds like ShadowRanger guessed correctly: you didn't write this code, and you want us to explain it to you, in particular, what that `if` block is doing. Is that correct? – PM 2Ring Oct 17 '17 at 02:16
  • 1
    BTW, you do know that `list` objects already have a `.remove` method, right? – PM 2Ring Oct 17 '17 at 02:17
  • @ShadowRanger It's not my code, I want to figure out this code snippet – ComplicatedPhenomenon Oct 17 '17 at 02:18
  • @PM2Ring Yes, I know. It 's nothing about re-inventing the wheels, I am learning about how to use very simple algorithm to implement these basic operations – ComplicatedPhenomenon Oct 17 '17 at 02:23
  • @cricket_007 Yes, you're right. The initial list is not modified, I construct a new list. – ComplicatedPhenomenon Oct 17 '17 at 02:29
  • Sure. Keep in mind `if len(items) == len(new_items)`... Should probably be `if value not in items`... Also, Your function can be simply written as `new_items = [x for x in items if x!=value]` or using the `filter()` function. https://stackoverflow.com/questions/3013449/list-filtering-list-comprehension-vs-lambda-filter – OneCricketeer Oct 17 '17 at 13:08
  • @cricket_007 Got it. – ComplicatedPhenomenon Oct 17 '17 at 13:36

2 Answers2

1

found is just a flag; while it's False (not found is True), you're checking each item against the target value. When you find a match, you set found to True, and bypass the item that matched (continue skips the rest of the body of the loop, returning to the top of the loop immediately, so append isn't called).

After that, not found is always False, and since and is a short-circuiting test, if the left hand side is False, then the right hand side isn't even checked. From there on, you just append all remaining items as you go. By using the flag and checking it first, you:

  1. Avoid removing more than one copy of value from the newly created list
  2. Avoid the work of comparing items once you've found a match (testing not somebool is the cheapest test available in Python beyond testing a compile time constant), speeding up the code a bit
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
1

Since found is initialized to be False it means that not found is evaluated to True, so while we're iterating the items and until we've found the item we're looking for, we'll compare each item == value and if it evaluates to True we'll enter the if body and execute two things:

  1. modify the value of found to True: which means that from now on we'll never enter that if block again
  2. continue we'll "jump" over the part that adds this item that we found

To sum it up: when we'll run into the first occurrence of value during iteration, we'll flip the value of the flag found and we'll skip the part that adds it to the new list. This will result in adding all the items but this one to the new-list.

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129