I have a list[] of items from which I'd like to display one randomly, but the displayed item must not repeat more than once in last x requests.
- list1 = item1, item2, item3, item4,
item5, item6, item7, item8, item9,
item 10
- Display a random selection
from the list above
- list2 = store the last displayed item in list2 which should only store 7
items, not more
- Display a random
selection from the list but make
sure it doesn't exist in the
list2
Is that the right way to do it? Either way, I'd like to know how to limit a list to store only 7 items?
Thanks
collections.deque is the only sequence type in python that naturally supports being bounded (and only in Python 2.6 and up.) If using python 2.6 or newer:
# Setup
from collections import deque
from random import choice
used = deque(maxlen=7)
# Now your sampling bit
item = random.choice([x for x in list1 if x not in used])
used.append(item)
If using python 2.5 or less, you can't use the maxlen argument, and will need to do one more operation to chop off the front of the deque:
while len(used) > 7:
used.popleft()
This isn't exactly the most efficient method, but it works. If you need speed, and your objects are hashable (most immutable types), consider using a dictionary instead as your "used" list.
Also, if you only need to do this once, the random.shuffle method works too.
Is this what you want?
list1 = range(10)
import random
random.shuffle(list1)
list2 = list1[:7]
for item in list2:
print item
print list1[7]
In other words, look at random.shuffle()
. If you want to keep the original list intact, you can copy it: list_copy = list1[:]
.
You could try using a generator function and call .next()
whenever you need a new item.
import random
def randomizer(l, x):
penalty_box = []
random.shuffle(l)
while True:
element = l.pop(0)
# for show
print penalty_box, l
yield element
penalty_box.append(element)
if len(penalty_box) > x:
# penalty time over for the first element in the box
# reinsert randomly into the list
element = penalty_box.pop(0)
i = random.randint(0, len(l))
l.insert(i, element)
Usage example:
>>> r = randomizer([1,2, 3, 4, 5, 6, 7, 8], 3)
>>> r.next()
[] [1, 5, 2, 6, 4, 8, 7]
3
>>> r.next()
[3] [5, 2, 6, 4, 8, 7]
1
>>> r.next()
[3, 1] [2, 6, 4, 8, 7]
5
>>> r.next()
[3, 1, 5] [6, 4, 8, 7]
2
>>> r.next()
[1, 5, 2] [4, 3, 8, 7]
6
>>> r.next()
[5, 2, 6] [4, 3, 8, 7]
1
>>> r.next()
[2, 6, 1] [5, 3, 8, 7]
4
>>> r.next()
[6, 1, 4] [3, 8, 2, 7]
5
Something like:
# Setup
import random
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list2 = []
# Loop for as long as you want to display items
while loopCondition:
index = random.randint(0, len(list1)-1)
item = list1.pop(index)
print item
list2.append(item)
if(len(list2) > 7):
list1.append(list2.pop(0))
I'd use set objects to get a list of items in list1 but not in list2:
import random
list1 = set(["item1", "item2", "item3", "item4", "item5",
"item6", "item7", "item8", "item9", "item10"])
list2 = []
while True: # Or something
selection = random.choice(tuple(list1.difference(set(list2))))
print(selection)
list2.append(selection)
if len(list2) > 7:
list2 = list2[-7:]