Python中的特定混洗列表

时间:2012-01-03 09:21:37

标签: python algorithm list

所以,我有一个小组列表

[['a', 'b'], ['c', 'd', 'e'], ['f']]

我需要洗牌这个列表的扁平化版本

[a, b, c, d, e, f]

使同一组的元素彼此相距一定距离。 E. g。

[a, c, b, d, f, e]而非[a, c, b, d, e, f],因为de属于同一群组。

我不在乎距离是否只是一个元素或更多元素,但任何元素必须不在其组的另一个元素附近。这有什么算法吗?

该算法还需要判断是否无法完成此操作。

4 个答案:

答案 0 :(得分:5)

此代码生成原始组列表的副本,并且每次从(每个时刻)最大剩余组中获取随机元素。不完全随机化,但是当没有超过一半所有元素的组时,它应该适用于任何情况。

import random

list_of_groups = [['a', 'b'], ['c', 'd', 'e'], ['f']]
l = [group[:] for group in list_of_groups] # make a copy
random.shuffle(l)
out = []
prev_i = -1
while any(a for a in l):
    new_i = max(((i,a) for i,a in enumerate(l) if i != prev_i), key=lambda x: len(x[1]))[0]
    out.append(l[new_i].pop(random.randint(0, len(l[new_i]) - 1)))
    prev_i = new_i

print out

答案 1 :(得分:2)

让我采取与当前答案不同的方法

基本原则是shuffle列表中的每个列表,sort它基于长度,zip_longest基于从列表传递的变量参数,最后{{3}列表然后打开它。特别要注意的是我们如何将列表作为变量args传递给迭代器,这使得生活变得更容易: - )

让我们说你的清单是

yourList=[['a', 'b'],['c', 'd', 'e'],['f']]

我的工作清单(复制后保存原始清单)

workList=yourList[::]

随机播放列表中的每个列表

[random.shuffle(x) for x in workList]

接下来,我们根据每个列表的长度对List进行排序

workList.sort(key=len,reverse=True)

然后最终链接到压缩的混洗列表

[x for x in itertools.chain(*[x for x in itertools.izip_longest(*workList)]) if x]

你的最终名单看起来像是

['e', 'b', 'f', 'c', 'a', 'd']

答案 2 :(得分:0)

只是一个快速而不是非常优雅的代码:

example = [[1, 2], [3, 4, 5], [6]]
result = []
block = None
last_block = None

while example:
    if block:
        last_block = block

    block = choice(example)

    if last_block:
        example.append(last_block)

    element = choice(block)
    result.append(element)

    block.remove(element)
    example.remove(block)
    example = [a for a in example if a]

print result

虽然可能发生的问题是只有一个块可供选择的情况。就像在这种情况下:

[1,6,2,3,4,5]

当然必须有某种方法来捕获这个异常,但是现在我希望这段代码可以让你知道如何解决你的问题。

  • 因偶尔发生异常而被编辑。
  • 忘记不使用像“list”这样的单词作为变量名。感谢您的评论 - 而不是更正

答案 3 :(得分:0)

我要给出“愚蠢”,直截了当的回答:只需将列表弄平,然后反复随机移动,直到你得到一个可接受的列表。

此方法具有在所有合法列表中均匀分布的特性,并且易于证明是正确且直接的代码。唯一的缺点是它可能会变慢 - 但考虑到另一条评论中提到的用例,我相信它会足够快。

至于“是否有可能” - 乍一看,我认为当且仅当没有任何一组有超过一半的元素时,应该是可能的。如果您考虑相邻的第一个和最后一个元素,请将“向上舍入”更改为“向下舍入”。