【问题标题】:List of permutations with repeated elements具有重复元素的排列列表
【发布时间】:2014-02-17 16:39:42
【问题描述】:

我正在尝试创建一个函数,该函数接收元素列表并递归返回包含该列表的所有排列(长度为 r)的列表。但是,如果列表中有-1,应该可以重复。

例如,对于 r = 2 的列表 [0, -1, 2],我希望返回 [0, -1], [-1, 0], [0, 2], [2, 0] , [-1, 2], [2, -1] 和 [-1, -1]。

到目前为止,这是我的功能:

def permutations(i, iterable, used, current, comboList, r):
    if (i == len(iterable):
        return
    if (len(current) == r):
        comboList.append(current)
        print current
        return
    elif (used[i] != 1):
        current.append(iterable[i])
        if (iterable[i][0] != -1):
            used[i] = 1 
    for j in range(0, len(iterable)):
        permutations(j+1, iterable, used, current, comboList, r)
        used[i] = 0
    return comboList

如您所见,我错误地尝试使用“已访问列表”来跟踪列表中的哪些元素已访问和未访问。

【问题讨论】:

  • -1 是在 Python 中给予特殊处理的丑陋值。你真正想做什么?这些数字代表什么?

标签: python list permutation


【解决方案1】:

利用itertools.permutations。您(显然)想要使用任意数量的 -1 以及可能的其他元素的排列;但您想丢弃重复项。

我们可以通过简单地提供与我们选择的元素一样多的 -1 来允许任意数量的 -1。

我们可以通过使用集合来丢弃重复项。

import itertools
def unique_permutations_with_negative_ones(iterable, size):
    # make a copy for inspection and modification.
    candidates = tuple(iterable)
    if -1 in candidates:
        # ensure enough -1s.
        candidates += ((-1,) * (size - candidates.count(-1)))
    return set(itertools.permutations(candidates, size))

让我们试试吧:

>>> unique_permutations_with_negative_ones((0, -1, 2), 2)
{(2, -1), (-1, 0), (-1, 2), (2, 0), (-1, -1), (0, -1), (0, 2)}

【讨论】:

    【解决方案2】:

    可能有一种更简洁的方法,但是像这样完全未经测试的代码:

    def apply_mask(mask, perm):
        return [perm.pop() if m else -1 for m in mask]
    
    def permutations(iterable, r):
        if -1 not in iterable:
            # easy case
            return map(list, itertools.permutations(iterable, r)))
        iterable = [x for x in iterable if x != -1]
        def iter_values():
            for mask in itertools.product((True, False), repeat=r):
                for perm in itertools.permutations(iterable, sum(mask)):
                    yield apply_mask(mask, list(perm))
        return list(iter_values())
    

    也就是说:首先遍历所有可能的“掩码”,其中掩码告诉您哪些元素将包含-1,哪些将包含另一个值。然后对于每个掩码,迭代“其他值”的所有排列。最后,使用 apply_mask 将值和 -1 插入结果中的正确位置。

    【讨论】:

    • 这很棒!十分感谢你的帮助。我不会想到面具的概念,但它在这里工作得非常好。说真的,谢谢!
    猜你喜欢
    • 2011-05-14
    • 2017-03-10
    • 1970-01-01
    • 1970-01-01
    • 2019-01-18
    • 2021-02-26
    • 2011-08-24
    • 2018-03-26
    • 1970-01-01
    相关资源
    最近更新 更多