混合两个列表python

时间:2015-07-29 18:26:59

标签: 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]

错误的输出示例:

# 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)

3 个答案:

答案 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]
>>> 

如果randinti,则在项目之前插入“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]