import random WORDS = ["Svitanok", "hogog", "gfgfgfg", "sdasd", "adam"] newwords = [] length = len(WORDS) newpos = "" while WORDS: newpos = random.randint(0, length-1) newwords.append(WORDS.pop(newpos)) WORDS.remove(WORDS[newpos]) print(newwords) 

In general, he wrote an algorithm for listing the WORDS list in random order. And stumbled upon the error "pop index out of range". I can not understand why the method goes beyond the boundaries? PS I know about shuffle, I just want to write code in this way.

    2 answers 2

    remove does not need to be called, pop already removes the item from the list. In addition, the length value needs to be updated at each iteration, because the WORDS list changes its size.

    • Thank you, I somehow forgot about length at all) - Fitzjerald

    Once: let's say, after several iterations of WORDS, we have become ["Svitanok"] .

    one)

     newpos = random.randint(0, length-1) 

    newpos can be 0, 1, 2, 3 or 4, because length = 5 (no one has changed this variable) and length-1 = 4, and randint includes both bounds in the interval from which the number is selected.

    Let's say newpos dropped 4.

    2)

     newwords.append(WORDS.pop(newpos)) 

    "Svitanok" is 0. There are no elements corresponding to indices 1, 2, 3, or 4. And newpos, we had just 4 - everything, going beyond the right limit of the list, pop drops.


    Two: let's go from the very beginning with a different situation.

    one)

     newpos = random.randint(0, length-1) 

    Let's say let it fall there 4

    2)

     newwords.append(WORDS.pop(newpos)) 

    WORDS = ["Svitanok", "hogog", "gfgfgfg", "sdasd"]

    newwords = ["adam"]

    3)

     WORDS.remove(WORDS[newpos]) 

    "Svitanok" is 0, "hogog" is 1, "gfgfgfg" is 2, "sdasd" is 3. And the newpos is 4. That's all, WORDS[newpos] falling, because 4 is going beyond the right limit list.


    The correct code is:

     import random WORDS = ["Svitanok", "hogog", "gfgfgfg", "sdasd", "adam"] newwords = [] while WORDS: newpos = random.randint(0, len(WORDS) - 1) newwords.append(WORDS.pop(newpos)) print(newwords) 
    • one
      Also, one-liner on hardcore: newwords = [WORDS.pop(random.randrange(len(WORDS))) for _ in range(len(WORDS))] - andreymal
    • Thank you!) Sorry, I can't raise my reputation yet) - Fitzjerald