-1

I wanted to clean a list by its length, removing small words.

    def is_word_min_than(number, word):
    if len(word) > number:
        return False
    else:
        return True


def filtrate_valid_words(query):
    min_len_number = 3
    for word in query:
        if is_word_min_than(min_len_number, word):
            query.remove(word)
    return query

filtrate_valid_words(['tacos',',','kkk'])

My last value was in the returned query, it hadnt to be there. I came up with the idea that this was happening because I was modifying the object I was iterating.

So I cloned my first list.

    def is_word_min_than(number, word):
    if len(word) > number:
        return False
    else:
        return True


def filtrate_valid_words(query):
    min_len_number = 3
    original_query = query
    for word in original_query:
        if is_word_min_than(min_len_number, word):
            query.remove(word)
    return query

filtrate_valid_words(['tacos',',','kkk'])

Same thing was happening, i dont know why. Anyway, I used the first solution that came to my mind.

    def is_word_min_than(number, word):
    if len(word) > number:
        return False
    else:
        return True


def filtrate_valid_words(query):
    min_len_number = 3
    words_to_delete = []
    for word in query:
        if is_word_min_than(min_len_number, word):
            words_to_delete.append(word)
    for word in words_to_delete:
        query.remove(word)
    return query

Now is working but Im just curious about why that happened. Thank you, I hope is not something really dumb. And if is that I would not be surprised, I have to go to sleep.

Laraconda
  • 667
  • 6
  • 15
  • 1
    *I have to go to sleep*?? – Bhargav Rao Mar 29 '15 at 12:02
  • 1
    @Lara: bad style to say "please solve my problem, I will sleep now." – Marcus Müller Mar 29 '15 at 12:04
  • Yes, maybe I cant see the obvious because Im tired. – Laraconda Mar 29 '15 at 12:04
  • Y said I have solved, Im just curious. – Laraconda Mar 29 '15 at 12:05
  • As Yossi mentions in his answer you haven't really cloned `query`, you've simply bound the same list object to a new name, so you can now refer to that object with `query` or `original_query`. Take a look at http://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list-in-python and SO member Ned Batchelder's excellent article [Facts and myths about Python names and values](http://nedbatchelder.com/text/names.html) – PM 2Ring Mar 29 '15 at 12:49

1 Answers1

3

Python does not support removing elements from list being iterated. This is exactly what happens in your first solution.

You might say that you copied the list in original_query = query, but this not the case. This line only copies the reference which does not make and difference.

Your first solution will work if you will actually make a copy of your input

original_query = list(query)

Or just use one-liner which is more efficient and readable

filtered = [word for word in query if len(word) > 3]
Yossi
  • 11,778
  • 2
  • 53
  • 66