我有以下列表:
a=['airplane','track','car','train']
我想创建一个列表,该列表会两次显示此列表的每个项目,但会阻止下两行的项目重复。这意味着飞机只能在飞机上出现,只要介于两个不同的项目之间,所以b将是一个很好的候选者:
b=['airplane','track','car','airplane','train','track','car' etc.]
但c不会:
c=['airplane,'track','airplane', etc.]
我在考虑某种暴力行动,其中: 1. a是重复的 2. random.shuffle(a) 3.测试重复(可能如下所示:
curWord[n]==curWord[n+1]
TRUE
重新洗牌并重新开始。 (我实际上并不知道命令是什么来指示python读取真值。我想if
语句会起作用,但对于FALSE
我不会&#39 ;我知道我如何指示python继续进行在任何情况下,虽然获得上述特定问题的答案对我自己的知识有好处,但我可以看到,我所考虑的实施可能需要很长时间,因为列表会增加。
有什么建议吗?
提前感谢您的帮助!
答案 0 :(得分:1)
如果您只需要一个包含每个元素的两个副本的列表,那么当原始列表超过2个元素时,这是否有理由不起作用?
In [138]: a=['airplane','track','car','train']
In [139]: a + a
Out[139]: ['airplane', 'track', 'car', 'train', 'airplane', 'track', 'car', 'train']
如果你问的是更抽象的问题,"我如何从列表元素的排列空间中进行抽样,使得它们不会出现在相同元素的两个元素之内?"然后以下应该工作。
请注意,获取元素出现两次的结构就像a + a
一样简单,然后您可以担心限制a + a
的排列 - 无需过度思考"如何做我得到两个"部分问题。
import random
def valid_duplicate_spacing(x):
for i, elem in enumerate(x):
if elem in x[i+1:i+3]:
return False
return True
def sample_permutations_with_duplicate_spacing(seq):
sample_seq = seq + seq
random.shuffle(sample_seq)
while not valid_duplicate_spacing(sample_seq):
random.shuffle(sample_seq)
return sample_seq
然后可以按如下方式使用:
In [165]: sample_permutations_with_duplicate_spacing(a)
Out[165]: ['airplane', 'train', 'track', 'car', 'train', 'track', 'car', 'airplane']
In [166]: sample_permutations_with_duplicate_spacing(a)
Out[166]: ['train', 'airplane', 'car', 'track', 'train', 'airplane', 'track', 'car']
如果您只是在谈论从列表中随机抽样,以便在下面两次抽奖中不替换样本,您可以使用生成器:
import random
def draw_with_delayed_replacement(seq):
drawn = random.choice(seq)
rejectables = [drawn]
yield drawn
drawn = random.choice(seq)
while drawn in rejectables:
drawn = random.choice(seq)
rejectables.append(drawn)
yield drawn
while True:
drawn = random.choice(seq)
if drawn in rejectables:
continue
else:
rejectables.pop(0)
rejectables.append(drawn)
yield drawn
然后您可以执行以下操作:
In [146]: foo = draw_with_delayed_replacement(a)
In [147]: foo.next()
Out[147]: 'car'
In [148]: foo.next()
Out[148]: 'train'
In [149]: foo.next()
Out[149]: 'track'
In [150]: foo.next()
Out[150]: 'car'
In [151]: foo.next()
Out[151]: 'train'
In [152]: foo.next()
Out[152]: 'track'
In [153]: foo.next()
Out[153]: 'car'
In [154]: foo.next()
Out[154]: 'airplane'
In [155]: foo.next()
Out[155]: 'track'
In [156]: foo.next()
Out[156]: 'train'
但是,在这种情况下,您无法保证您可以获得每个元素恰好出现两次的样本,这对于小型列表来说效率可能不高。
答案 1 :(得分:1)
这是我的解决方案,但不能保证每个令牌只出现n次。
我可以轻松地扩展我的解决方案以保证这一点,但这会导致可能出现的死锁情况,然后才能检查。
>>> def magicsequence(tokens, length):
... sequence = []
... while len(sequence) < length:
... candidate = random.choice(tokens)
... if candidate not in sequence[-2:]:
... sequence.append(candidate)
... return sequence
答案 2 :(得分:0)
这是一个满足约束的解决方案,并且总是返回每个元素两次的列表。它在O(n ^ 2)时间内运行,其中n是列表的长度。
from collections import Counter
from itertools import permutations
from random import choice, shuffle
def shuffle_with_constraints(x):
if len(x) < 3:
raise ValueError("Lists with length less than 3 have no valid shuffles")
output = []
#a counter representing how many times we still need to insert an element
available = Counter(x*2)
while available:
if len(output) == len(x)*2-6: #we just need to insert six elements
distinct = len(available) #how many distinct elements we need to insert
if distinct == 6:
pass #there is no problem
elif distinct == 3: #only six possibilities
end = list(available)
shuffle(end)
return output + end*2
else:
#enumerate all 720 permutations and select a valid one
possibles = [possible for possible in permutations(available.elements())
if valid_6_shuffle(possible)]
return output+list(choice(possibles))
#choose a valid element and append it to the output
next = choice(list(set(available)-set(output[-2:])))
output.append(next)
#remove it from the availables
if available[next] == 2:
available[next] -= 1
else:
del available[next]
return output
def valid_6_shuffle(x):
for a,b,c in zip(x,x[1:],x[2:]):
if a==b or b==c or a==c:
return False
return True