我正在尝试创建一个函数来混合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]
错误的输出示例:
# There are more than two '1' standing next two each other
output = [1,1,1,2,2,1,2,1,2,2]
这是我的解决方案:
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
问题是输出的输出有两个以上相同的元素,它们彼此相邻,或者输出列表的长度比两个列表的组合长度长
例如我的一个输出
[2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2]
我在这里做错了什么?
修改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)
结果很好,除了代码执行无限制,我必须使用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)
答案 0 :(得分:6)
你可以实现一个贪心算法,试图产生最常见的项目 尽可能频繁地(即最多两次),然后产生下一个最常见的项目 必要时。
这比随机随机搜索有两个优点:
随着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
它可以识别何时没有解决方案,而随机随机搜索 如果访问的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')
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]
答案 1 :(得分:1)
您可以使用shuffle
中的random
:
list1=[1,1,1,1,1]
list2=[2,2,2,2,2]
import random
lst = list1+list2
print(lst)
while True:
random.shuffle(lst)
if not any([lst[i-2]==lst[i-1]==lst[i]for i in range(len(lst))]):
break
print(lst)
结果:
[1, 2, 1, 1, 2, 1, 2, 2, 1, 2]
说明:我添加了两个列表并suffle
。然后我重复shuffle
,直到没有3个相同的连续数字。正如评论指出的那样,可能需要很长时间,但很容易限制迭代次数
试图解释为什么你的代码不起作用:
def guyGenerator(toughGuy,softGuy):
import random
i = 0
while len(softGuy) > 0:
temp = softGuy[:1]
while i < len(toughGuy)- 1:
if toughGuy[i] == toughGuy[i + 1] == 2:
# you insert temp[0]: it can be inserted before i
# for lst = [0, 1, 2, 3]
# lst.insert(0, "X") result in ["X", 0, 1, 2, 3]
# But then, the next time, you'll test exactly the
# same thing: because you increment i and have move all
# the items of toughGuy one char to the right
# and that, without reducing softGuy len.
toughGuy.insert(random.randint(i, i + 1), temp[0])
i = i + 1
softGuy = softGuy[1:]
return toughGuy
print(guyGenerator([2,2,2,2,2], [1,1,1,1,1]))
好?我很清楚?
lst = [1, 2, 3, 4, 5]
>>> lst.insert(0, "X")
>>> lst
['X', 1, 2, 3, 4, 5]
>>> lst = [1, 2, 3, 4, 5]
>>> lst.insert(1, "X")
>>> lst
[1, 'X', 2, 3, 4, 5]
>>>
如果randint
给i
,则在项目之前插入“X”
你增加我和你所以我找到完全相同的元素:
>>> lst = [1, 2, 3, 4, 5]
>>> lst.insert(0, "X")
>>> lst
['X', 1, 2, 3, 4, 5]
>>> lst.insert(1, "X")
>>> lst
['X', 'X', 1, 2, 3, 4, 5]
>>>
这就是问题所在,因为你还在同一个循环中!
因此,在将softGuy减少一个元素之前,您可以插入多个temp [0]。是吗?
任何建议都会受到欢迎!
答案 2 :(得分:0)
您可以采用受气泡排序算法启发的方法。这将包括交换数字以打破三值条纹,直到不需要更多交换为止。换句话说,每次a,a,a,b
与前面的b
交换a
使其成为a,a,b,a
。
list1 = [1,1,1,1,1,1,1,1,1,1]
list2 = [2,2,2,2,2]
output = list1+list2
swapping = True
while swapping:
swapping = False
for i in range(3,len(output)):
if output[i] != output[i-1] and output[i-3:i-1] == output[i-2:i]:
swapping = True
output[i-1:i+1] = output[i-1:i+1][::-1]
print(output)
[1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2]