Показать случайный выбор (Python) - PullRequest
2 голосов
/ 06 января 2010

У меня есть список [] элементов, из которых я хотел бы отобразить один случайным образом, но отображаемый элемент не должен повторяться более одного раза в последних x запросах.

  1. list1 = item1, item2, item3, item4, элемент 5, элемент 6, элемент 7, элемент 8, элемент 9, пункт 10
  2. Показать случайный выбор из списка выше
  3. list2 = сохранить последний отображаемый элемент в list2, который должен хранить только 7 шт, не более
  4. Показать случайный выберите из списка, но сделайте уверен, что он не существует в песни2

Это правильный способ сделать это? В любом случае, я хотел бы знать, как ограничить список для хранения только 7 элементов?

Спасибо

Ответы [ 5 ]

7 голосов
/ 06 января 2010

collection.deque - единственный тип последовательности в python, который, естественно, поддерживает ограничение (и только в Python 2.6 и выше). Если используется python 2.6 или новее:

# 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)

Если вы используете Python 2.5 или менее, вы не можете использовать аргумент maxlen, и вам нужно будет сделать еще одну операцию, чтобы отрубить лицевую сторону deque:

while len(used) > 7:
    used.popleft()

Это не самый эффективный метод, но он работает. Если вам нужна скорость, и ваши объекты являются хэшируемыми (большинство неизменяемых типов), рассмотрите возможность использования словаря вместо этого в качестве своего «используемого» списка.

Кроме того, если вам нужно сделать это только один раз, метод random.shuffle также будет работать.

4 голосов
/ 06 января 2010

Это то, что вы хотите?

list1 = range(10)
import random
random.shuffle(list1)
list2 = list1[:7]
for item in list2:
    print item
print list1[7]

Другими словами, посмотрите на random.shuffle(). Если вы хотите сохранить исходный список без изменений, вы можете скопировать его: list_copy = list1[:].

2 голосов
/ 06 января 2010

Можно попробовать использовать функцию генератора и вызывать .next() всякий раз, когда вам нужен новый элемент.

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)

Пример использования:

>>> 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
1 голос
/ 06 января 2010

Я бы использовал набор объектов для получения списка элементов в list1, но не в 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:]
1 голос
/ 06 января 2010

Что-то вроде:

# 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))
...