简体   繁体   English

具有重复元素的排列列表

[英]List of permutations with repeated elements

I'm trying to create a function that takes in a list of elements and recursively returns a list containing all permutations (of length r) of that list. 我正在尝试创建一个接受元素列表并递归返回包含该列表的所有排列(长度为r)的列表的函数。 However, if there is a -1 on the list, it should be able to be repeated. 但是,如果列表上有-1,则应该可以重复。

For example, with the list [0, -1, 2] with r = 2 I would want returned [0, -1], [-1, 0], [0, 2], [2, 0], [-1, 2], [2, -1] and [-1, -1]. 例如,对于具有r = 2的列表[0,-1,2],我想返回[0,-1],[-1,0],[0,2],[2,0],[- 1,2],[2,-1]和[-1,-1]。

Here is my function so far: 到目前为止,这是我的功能:

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

As you can see, I'm incorrectly trying to utilized a "visited list" that keeps track of what elements of the list have and have not been visited. 如您所见,我错误地尝试利用“已访问列表”来跟踪列表中哪些元素已被访问和尚未被访问。

There's probably a neater way, but something like this completely untested code: 可能有一种更整洁的方式,但是像这样的完全未经测试的代码:

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

That is to say: first iterate over all possible "masks", where the mask tells you which elements will contain -1 and which will contain another value. 也就是说:首先遍历所有可能的“掩码”,其中掩码告诉您哪些元素将包含-1,哪些元素将包含另一个值。 Then for each mask, iterate over all permutations of the "other values". 然后,对于每个掩码,遍历“其他值”的所有排列。 Finally, use apply_mask to slot the values and the -1s into the right places in the result. 最后,使用apply_mask将值和-1放入结果中的正确位置。

Leverage itertools.permutations . 利用itertools.permutations You (apparently) want permutations that use any number of -1s, as well as possibly the other elements; 您(显然)希望使用任何数量的-1以及所有其他元素的排列; but you want to discard duplicates. 但您要舍弃重复项。

We can allow any number of -1s by simply providing as many -1s as elements we are choosing. 通过提供与我们选择的元素一样多的-1,我们可以允许任意数量的-1。

We can discard duplicates by using a set. 我们可以使用集合来丢弃重复项。

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

Let's try it: 让我们尝试一下:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM