我试图创建一个函数来混合python中的两个列表,或者我更确切地说将list2的元素放入list1.要求在输出列表中,接下来彼此不超过两个元素具有相同的值
例如:
list1 = [1,1,1,1,1]
list2 = [2,2,2,2,2]
output = [1,1,2,1,2,2,1,2,1,2]
Run Code Online (Sandbox Code Playgroud)
错误的输出示例:
# There are more than two '1' standing next two each other
output = [1,1,1,2,2,1,2,1,2,2]
Run Code Online (Sandbox Code Playgroud)
这是我的解决方案:
def guyGenerator(toughGuy,softGuy):
i = 0
while len(softGuy) > 0:
temp = softGuy[:1]
while i < len(toughGuy) - 1:
if toughGuy[i] == toughGuy[i + 1] == 2:
toughGuy.insert(random.randint(i, i + 1), temp[0])
i = i + 1
softGuy = softGuy[1:]
return toughGuy
Run Code Online (Sandbox Code Playgroud)
问题是输出的输出中有两个以上相同的元素,它们彼此相邻,或者输出列表的长度比两个列表的组合长度长
例如我的一个输出
[2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2]
Run Code Online (Sandbox Code Playgroud)
我在这做错了什么?
编辑1
Clodion问我,所以我把它放在这里
结果可以是随机的,只要它们满足问题中的要求即可.只要不超过两个彼此相邻的元素具有相同的值,元素的顺序就无关紧要
编辑2
我试图通过使用Clodion解决方案创建一个可迭代类来搞乱.这是新代码:
import random
class GuyGenerator:
def __init__(self,toughGuyList,softGuyList):
self.toughGuyList = toughGuyList
self.softGuyList = softGuyList
def __iter__(self):
return self
def __next__(self):
listSum = self.toughGuyList + self.softGuyList
while True:
res = random.sample(listSum,len(listSum))
if not any([res[i-2]==res[i-1]==res[i] for i in range(len(listSum))]):
break
return res
toughGuy = ['tough','tough','tough','tough','tough','tough','tough','tough']
softGuy = ['soft','soft','soft','soft','soft','soft','soft','soft']
for guy in GuyGenerator(toughGuy,softGuy):
print(guy)
Run Code Online (Sandbox Code Playgroud)
结果非常好,除了代码执行无限制,我必须使用KeyboardInterrupt来停止代码.在这种情况下我做错了什么?因为我是Python和Iterator的新手,所以我会感激彻底的解释
编辑3
解决了迭代器问题,比我想象的要容易.事实证明,在iter中返回的是在调用for循环时类返回的内容
解:
def __iter__(self):
listSum = self.listRandom1 + self.listRandom2
while True:
self.res = random.sample(listSum,len(listSum))
if not any([self.res[i-2]==self.res[i-1]==self.res[i] for i in range(len(listSum))]):
break
return iter(self.res)
Run Code Online (Sandbox Code Playgroud)
您可以实现一种贪婪算法,该算法尽可能频繁地产生最常见的项目(即最多两次),然后在必要时产生下一个最常见的项目.
与随机随机搜索相比,这有两个优点:
随着items增长的长度,贪婪算法要快得多:
In [223]: %timeit list(intermix([1]*10+[2]*5))
10000 loops, best of 3: 39.8 µs per loop
In [222]: %timeit intermix_random([1]*10+[2]*5)
100 loops, best of 3: 6.85 ms per loop
Run Code Online (Sandbox Code Playgroud)它可以识别何时没有解决方案,而随机shuffle搜索将永久循环,如果访问的shuffle没有被缓存.
import collections
def intermix(items, nconsecutive=2):
counter = collections.Counter(items)
# sort from most common to least common
items = sorted(items, key=counter.get, reverse=True)
N = len(items)
count = 0
# remember the last two values
last = []
for i in range(N):
val = items[i]
if len(last) < nconsecutive:
if last and val == last[-1]:
last.append(val)
else:
last = [val]
counter[val] -= 1
yield val
else:
# last is full; find a different value
for j in range(i, N):
if items[j] != last[-1]:
items[i], items[j] = items[j], items[i]
val = items[i]
last = [val]
counter[val] -= 1
# as items are yielded, the meaning of "most common" can change.
items[i+1:] = sorted(items[i+1:], key=counter.get, reverse=True)
yield val
break
else:
raise ValueError('No solution possible')
Run Code Online (Sandbox Code Playgroud)
In [184]: list(intermix([1,1,1,1,1,2,2,2,2,2]))
Out[184]: [1, 1, 2, 2, 1, 2, 2, 1, 2, 1]
In [185]: list(intermix([1,0,1,1,2,1,0,1,1,1,2]))
Out[185]: [1, 1, 0, 1, 1, 2, 1, 1, 2, 1, 0]
In [186]: list(intermix([1,0,1,1,2,1,0,1,1,1,1,1,1,2]))
Out[186]: [1, 1, 0, 1, 1, 2, 1, 1, 2, 1, 1, 0, 1, 1]
In [187]: list(intermix([1,0,1,1,2,1,0,1,1,1,1,1,1,1,2]))
ValueError: No solution possible
In [188]: list(intermix([1,0,1,1,2,1,0,1,1,1,1,1,1,1,2], nconsecutive=3))
Out[188]: [1, 1, 1, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0]
Run Code Online (Sandbox Code Playgroud)