创建没有连续重复的随机列表时,索引超出范围错误

时间:2019-07-14 21:54:16

标签: python list random

我正在尝试生成100个元素的列表,该列表由1到4个随机分布的数字组成,但是没有连续的重复。我不想确定数字1到4是否出现相同的次数,我希望它是完全随机的,除了没有连续的重复。我写了一些似乎一直在做的代码,直到它停止并说 list index out of range,但是我不知道为什么会发生此错误。

from random import randint

guesses = []

for x in range (0, 99):

    guess = randint(1,4)
    guesses.append(guess)

    if x> 0 and guesses[x] == guesses[x-1]:
       guesses.remove(guess)

 print(guesses)

它应该看起来像这样:

123421342312321423124213...23142314213

7 个答案:

答案 0 :(得分:3)

您的问题是,即使您删除数字而不是减少数字,该数字仍会不断增加。我建议改用while循环。另外,您只应在需要时将号码添加到列表中,而不要添加后再将其删除。

from random import randint

guesses = [randint(1,4)]
x = 1

while x < 100:

    guess = randint(1,4)

    if guess != guesses[x-1]:
       guesses.append(guess)
       x += 1

print(guesses)

答案 1 :(得分:1)

您的代码可以正常工作,而不是删除与之匹配的元素,而是替换它直到不起作用为止。

from random import randint

guesses = [randint(1,4)]

for x in range (1, 100):

    guess = randint(1,4)
    guesses.append(guess)

    while guesses[x] == guesses[x-1]:
        guesses[x] = randint(1,4)

两个备选方案:

您可以创建一组选择:

{1, 2, 3, 4}

然后在每次迭代中从集合中的最后一个项中请求random.choicechoice需要一些可索引的内容,因此您每次都需要转换为列表,但是如果存在瓶颈,可能有一些方法可以使它更有效:

from random import choice

choices = {1, 2, 3, 4}
l = [choice(list(choices))]  # start with one random choice

for i in range(99):
    l.append(choice(list(choices - {l[-1]})))   

这似乎很统一:

from collections import Counter

counts = Counter(l)
counts

Counter({3: 26, 2: 25, 1: 26, 4: 23})

使用迭代器
您可以使用延迟评估的迭代器来完成所有这些工作,然后只需选择所需长度的islice()

from random import randint
from itertools import tee, islice

#generator to makes random ints between start and stop
def randIt(start, stop):
    while True:
        yield randint(1,4)

rands, prevs = tee(randIt(1, 4))
next(prevs)

# non_dupes is a generator that makes non-repeating rands
non_dupes = (r for r, i in zip(rands, prevs) if r!=i)

# use itertools islice or a loop to get the number you want
# or just call `next(non_dupes)` for one:
list(islice(non_dupes, 0, 100))

答案 2 :(得分:1)

这是使用numpy的解决方案

from time import time

import numpy as np



def solve_random_non_consecutive(minValue,maxValue,size):
    # initial guess
    a = np.random.randint(minValue,maxValue,size)
    # indexes where a[i] == a[i-1]
    x = np.where(np.diff(a) == 0)[0]
    # as long as we have consecutive duplicates
    while len(x) > 0:
        # rerandomize all indexes
        a[x] = np.random.randint(minValue,maxValue,len(x))
        # find all duplicates
        x = np.where(np.diff(a) == 0)[0]
    return a

s = time()
print(solve_random_non_consecutive(1,5,1000000))
print("Took %0.2fs to solve"%(time()-s)) # took ~ 0.17 seconds to generate 1MIL 
# any of the solutions using iteration took ~ 10 seconds to generate 1 mil

有一些警告,因为它随机地重新填充数据,所以每次运行的时间可能会有所不同

答案 3 :(得分:0)

您仅生成99个元素。范围(0,99)从0到98,包括0到总共99个元素。

此外,代码中要删除重复猜测的部分需要将x设置为x-1。这样,要创建的每个元素的“计数器”并不比实际拥有的元素多1。 / p>

此外,当删除此元素时,该方法将删除对象的第一个实例,该实例等于变量guess,不一定是您刚刚添加的对象。您应该使用.pop()查看我截屏的python中的示例。

for x in range (0, 100):

    guess = randint(1,4)
    guesses.append(guess)

    if x> 0 and guesses[x] == guesses[x-1]:
       guesses.pop()
       x = x - 1

enter image description here

答案 4 :(得分:0)

本周我遇到了类似的问题,我的解决方案是每次删除索引时都必须调整计数器(x看起来像您一样),因为数组变短了,所以事情开始四处移动。

答案 5 :(得分:0)

当您从猜测数组中删除元素时,它的长度会减少

使用此代码

from random import randint

guesses = []
x = 0
while x < 100:

    guess = randint(1,4)
    guesses.append(guess)

    if x > 0 and guesses[x] == guesses[x-1]:
        guesses.pop()
    else:
        x += 1

print(guesses)

答案 6 :(得分:0)

问题是,一旦删除元素,x就会变得大于数组的大小

所以guesss [x]超出范围,因为x> = guess.size()