0

I have a list [1,2,3,3], and I want to select a random element from this list multiple times. However, I don't want my random generator to select the same element from the same index more than once.

What I'm currently have:

[1,2,3,3] --> [2] with index 1
[1,2,3,3] --> [1] with index 0       
[1,2,3,3] --> [2] with index 1       (this is wrong because chose the same index)

What I want is:

[1,2,3,3] --> [2] with index 1
[1,2,3,3] --> [1] with index 0       
[1,2,3,3] --> [3] with index 3       
[1,2,3,3] --> [3] with index 4       (this is perfect, no repeats!)

What should I do to solve this issue? The function random.choice(...) itself doesn't solve this.

UPDATE: I noticed some of you recommended me to use shuffle. It was a really good idea. But, what if I want to keep track of the original index too at later time? I don't think shuffle and pop could do that, right?

Pang
  • 9,564
  • 146
  • 81
  • 122
ThomasWest
  • 485
  • 1
  • 7
  • 21
  • please see this post; https://stackoverflow.com/questions/9755538/how-do-i-create-a-list-of-unique-random-numbers – SteveJ Dec 01 '17 at 05:16
  • I would use `shuffle` or something, then pop the list until it's empty. – Shadow Dec 01 '17 at 05:17

4 Answers4

2

The following generator produces (index, element) pairs in random order while keeping the original list as it is:

def gen(lst):
    lst2 = list(enumerate(lst))
    random.shuffle(lst2)
    for x in lst2:
        yield x

l = [1, 2, 3, 3]
for index, elmnt in gen(l):
    # do stuff
    print(index, elmnt)
# 0 1
# 2 3
# 3 3
# 1 2
user2390182
  • 72,016
  • 6
  • 67
  • 89
1

shuffle the list once and then pop() returns the last element, reducing the list.

>>> from random import shuffle
>>> a=[1,2,3,3]
>>> shuffle(a)
>>> a.pop()
3
>>> a.pop()
2
>>> a.pop()
3
>>> a.pop()
1

edit: to keep track of the index using enumerate

from random import shuffle
a=[1,2,3,3]
b=list(enumerate(a))
shuffle(b)
b.pop()

(3, 3)

docs: enumerate and random.shuffle

thanasisp
  • 5,855
  • 3
  • 14
  • 31
0

You can use random.sample.

random.sample(population, k)

Returns a k length list of unique elements chosen from the population sequence or set. Used for random sampling without replacement.

kchawla-pi
  • 408
  • 5
  • 12
0

Use @thanasisp's solution and use shuffle along with zip to keep track of the indices:

a = range(10, 15)
b = zip(a, range(len(a))) # pairs of values and indices

import random
random.shuffle(list(b)) # list() evaluates the zip

a_shuffle, idxes = list(zip(*b))
# e.g. [(13, 11, 10, 14, 12), (3, 1, 0, 4, 2)]
Jan Christoph Terasa
  • 5,781
  • 24
  • 34