Thread: list problem

    #1
  1. ID10T
    Devshed Novice (500 - 999 posts)

    Join Date
    Feb 2004
    Location
    Yes
    Posts
    632
    Rep Power
    27

    list problem


    Hi i was tring to remove all strings with less than two chars from a list as follows:

    for word in list:
    if len(word) < 3:
    list.remove(word)

    The problem is that this code only removes(or checks) every second entry?!?

    Whats going on?


    The original list is: 11, 22, 33, 44, 55, 66, 77, 88, 99,

    but only 11, 33, 55, 77, and 99 are removed . . .
  2. #2
  3. Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Dec 2004
    Location
    Meriden, Connecticut
    Posts
    1,797
    Rep Power
    154
    Code:
    >>> list = ['11', '22', '33', '44', '55', '66', '77', '88', '99'];
    >>> for word in list:
            if(len(word) < 3):
                list.remove(word);
    
                
    >>> list
    ['22', '44', '66', '88']
    >>>
    Yes, I got the same thing. I'm not sure why it does that, but if you run that for loop 4 times, it will remove them all. That's all I can say.
  4. #3
  5. ID10T
    Devshed Novice (500 - 999 posts)

    Join Date
    Feb 2004
    Location
    Yes
    Posts
    632
    Rep Power
    27
    Hmm yea but its hardly good practice.

    You can loop through it, test each entry and put it in a new list if it passes.

    Still id like to know whats going on & if theres a proper way . . anyone?
  6. #4
  7. Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Dec 2004
    Location
    Meriden, Connecticut
    Posts
    1,797
    Rep Power
    154
    I'm still unsure of what is going on, but I decided that the following would be a good way to get around this, using a while loop:
    Code:
    >>> list = ['11', '22', '33', '44', '55', '66', '77', '88', '99'];
    >>> while(len(list) >= 1):
    	for w in list:
    	    if(len(w) < 3):
    		list.remove(w);
    If a while loop is going to cause trouble because you are other loops running for whatever reasons. Then import the threading module, stick the code I gave into a function, and use the threading module's Timer function to run that function. Once again, I don't see why certain elements in the list are remaining.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2004
    Posts
    394
    Rep Power
    51
    Hi!

    Ok, here is what I think is going on:
    Code:
    list = ['11', '22', '33', '44', '55', '66', '77', '88', '99'];
    for word in list:
    So, word is the first element in the list, '11'. We check if its length is < 3 ... yes it is, so we delete it. The list now looks like this
    Code:
    ['22', '33', '44', '55', '66', '77', '88', '99']
    The second round in our for-loop: word is now the "second" element in the list. But the second element is now '33', and not as you thought '22'. So we jumped over '22'. That's why only every second element is checked.

    EDIT: Oh, here is how you can do it:
    Code:
    list = ['11', '22', '33', '44', '55', '66', '77', '88', '99']
    for word in list[:]:
        if len(word) < 3:
            list.remove(word)
    Regards, mawe

    Comments on this post

    • Civ247 agrees : good stuff, thanks!
  10. #6
  11. Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Dec 2004
    Location
    Meriden, Connecticut
    Posts
    1,797
    Rep Power
    154
    Very good job mawe. I never would have figured that one out. Would using a while loop be a good idea then?

    Edit: Ignore this post, I was posting as mawe edited his post.
    Last edited by †Yegg†; May 30th, 2005 at 03:30 PM.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2004
    Posts
    394
    Rep Power
    51
    Sorry, I posted my solution a bit too late
    Your while-loop would run forever, if one of the list elements had a length > 2, like in ['11','22','33','4444'].
  14. #8
  15. Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Dec 2004
    Location
    Meriden, Connecticut
    Posts
    1,797
    Rep Power
    154
    I left out the break statement after the while loops for loop. I only coded that according to what the elements inside the list were.

    Edit: Wait, my while loop wouldn't go forever. It does while len(list is alteast equal to 1. After all items are removed, it will be 0 and nothing will happen. Even with this though, there should be a check for when len(list) equals 0, to then run a break statement.
    Last edited by †Yegg†; May 30th, 2005 at 03:49 PM.
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2004
    Posts
    394
    Rep Power
    51
    Originally Posted by †Yegg†
    Wait, my while loop wouldn't go forever. It does while len(list is alteast equal to 1. After all items are removed, it will be 0 and nothing will happen.
    Yes, but in my example with ['11','22','33','4444'], the last element ('4444') will never be removed. So len(list) will stay 1 and the while-loop will run for the rest of our lives (or until you hit Strg-C ).
    BTW: To remove all elements from a list, you don't need a while loop, cou can just write list = [ ]
  18. #10
  19. ID10T
    Devshed Novice (500 - 999 posts)

    Join Date
    Feb 2004
    Location
    Yes
    Posts
    632
    Rep Power
    27
    Originally Posted by mawe
    Hi!

    Ok, here is what I think is going on:
    Code:
    list = ['11', '22', '33', '44', '55', '66', '77', '88', '99'];
    for word in list:
    So, word is the first element in the list, '11'. We check if its length is < 3 ... yes it is, so we delete it. The list now looks like this
    Code:
    ['22', '33', '44', '55', '66', '77', '88', '99']
    The second round in our for-loop: word is now the "second" element in the list. But the second element is now '33', and not as you thought '22'. So we jumped over '22'. That's why only every second element is checked.

    EDIT: Oh, here is how you can do it:
    Code:
    list = ['11', '22', '33', '44', '55', '66', '77', '88', '99']
    for word in list[:]:
        if len(word) < 3:
            list.remove(word)
    Regards, mawe
    ->11,22,33,44,55,66,77,88,99

    pass 1 take out the 11

    ->22,33,44,55,66,77,88,99

    pass 2 take out 33

    ->22,44,55,66,77,88,99

    pass 3 take out 55

    ->22,44,66,77,88,99

    pass 4 take out 77

    ->22,44,66,88,99

    pass 5 take out 99

    -> 22,44,66,88

    You have to admit the logic of it is beautiful

IMN logo majestic logo threadwatch logo seochat tools logo