我正在尝试生成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
答案 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.choice
。 choice
需要一些可索引的内容,因此您每次都需要转换为列表,但是如果存在瓶颈,可能有一些方法可以使它更有效:
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
答案 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()