混合两个列表python

Tua*_*inh 8 python list

我试图创建一个函数来混合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)

unu*_*tbu 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
    
    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)