两个列表 - 找到所有排列 - 甚至是多对一

问题描述 投票:0回答:3

我有两个列表,我需要找到所有排列。

关键是可以分配多个“数字”项目(如下例所示)。也不允许分配。

所以这个:

names = ['a', 'b']
numbers = [1, 2]

会变成这样(列表顺序无关紧要,所以

[1, 2] = [2, 1]

[
    "not only this"
    {'a': [1], 'b': [2]},
    {'a': [2], 'b': [1]},
    "but also"
    {'a': [1], 'b': []},
    {'a': [2], 'b': []},
    {'a': [1, 2], 'b': []},
    {'a': [], 'b': [1]},
    {'a': [], 'b': [2]},
    {'a': [], 'b': [1, 2]},

]

或者例如这个:

names = ['a', 'b']
numbers = [1, 2, 3]

会按照以下方式去做:

[
    {'a': [], 'b': []},
    {'a': [1], 'b': [2]},
    {'a': [1], 'b': [3]},
    {'a': [2], 'b': [1]},
    {'a': [2], 'b': [3]},
    {'a': [3], 'b': [1]},
    {'a': [3], 'b': [2]},
    "but also"
    {'a': [], 'b': [1]},
    {'a': [], 'b': [1, 2]},
    {'a': [], 'b': [1, 2, 3]},
    {'a': [1], 'b': []},
    {'a': [1], 'b': [2]},
    {'a': [1], 'b': [2, 3]},
    {'a': [1, 2], 'b': []},
    {'a': [1, 2], 'b': [3]},
    {'a': [1, 2, 3], 'b': []},
    {'a': [2], 'b': []},
    {'a': [2], 'b': [1]},
    {'a': [2], 'b': [1, 3]},
    {'a': [2, 3], 'b': []},
    {'a': [2, 3], 'b': [1]},
    "etc..."
]

创建一个单独的问题关于列表顺序何时重要。

python permutation
3个回答
3
投票

这应该做你想做的事:

import itertools

def f(p, names, numbers):
    r = {name : [] for name in names}
    for i, j in enumerate(p):
        if j >= 0:
            r[names[j]].append(numbers[i])

    return r

def get_vals(names, numbers):
    p_iter = itertools.product(range(-1, len(names)), repeat=len(numbers))

    return [f(p, names, numbers) for p in p_iter]

您可以调用

get_vals
返回所需的列表。这是一个小例子:

names = ['a', 'b']
numbers = [1, 2]

r = get_vals(names, numbers)

for d in r:
    print(d)

这打印:

{'a': [], 'b': []}
{'a': [2], 'b': []}
{'a': [], 'b': [2]}
{'a': [1], 'b': []}
{'a': [1, 2], 'b': []}
{'a': [1], 'b': [2]}
{'a': [], 'b': [1]}
{'a': [2], 'b': [1]}
{'a': [], 'b': [1, 2]}

这是更大的例子:

names = ['a', 'b']
numbers = [1, 2, 3]

r = get_vals(names, numbers)

for d in r:
    print(d)

这打印:

{'a': [], 'b': []}
{'a': [3], 'b': []}
{'a': [], 'b': [3]}
{'a': [2], 'b': []}
{'a': [2, 3], 'b': []}
{'a': [2], 'b': [3]}
{'a': [], 'b': [2]}
{'a': [3], 'b': [2]}
{'a': [], 'b': [2, 3]}
{'a': [1], 'b': []}
{'a': [1, 3], 'b': []}
{'a': [1], 'b': [3]}
{'a': [1, 2], 'b': []}
{'a': [1, 2, 3], 'b': []}
{'a': [1, 2], 'b': [3]}
{'a': [1], 'b': [2]}
{'a': [1, 3], 'b': [2]}
{'a': [1], 'b': [2, 3]}
{'a': [], 'b': [1]}
{'a': [3], 'b': [1]}
{'a': [], 'b': [1, 3]}
{'a': [2], 'b': [1]}
{'a': [2, 3], 'b': [1]}
{'a': [2], 'b': [1, 3]}
{'a': [], 'b': [1, 2]}
{'a': [3], 'b': [1, 2]}
{'a': [], 'b': [1, 2, 3]}

2
投票

已经发布了更好的答案,但这是使用

itertools
的一个很好的练习,这也有效:

from itertools import combinations, product

names = ['a', 'b']
numbers = [1, 2, 3]

perm_list = [list(perm) for perm_len in range(len(numbers)+1) for perm in combinations(numbers, perm_len)]   # generate permutations

perm_dict = [{names[0]: perm1, names[1]: perm2} for perm1, perm2 in product(perm_list, perm_list) if not set(perm1) & set(perm2)]   # get all possible non-overlapping combinations

for perm_combination in perm_dict:
    print(perm_combination)

输出:

{'a': [], 'b': []}
{'a': [], 'b': [1]}
{'a': [], 'b': [2]}
{'a': [], 'b': [3]}
{'a': [], 'b': [1, 2]}
{'a': [], 'b': [1, 3]}
{'a': [], 'b': [2, 3]}
{'a': [], 'b': [1, 2, 3]}
{'a': [1], 'b': []}
{'a': [1], 'b': [2]}
{'a': [1], 'b': [3]}
{'a': [1], 'b': [2, 3]}
{'a': [2], 'b': []}
{'a': [2], 'b': [1]}
{'a': [2], 'b': [3]}
{'a': [2], 'b': [1, 3]}
{'a': [3], 'b': []}
{'a': [3], 'b': [1]}
{'a': [3], 'b': [2]}
{'a': [3], 'b': [1, 2]}
{'a': [1, 2], 'b': []}
{'a': [1, 2], 'b': [3]}
{'a': [1, 3], 'b': []}
{'a': [1, 3], 'b': [2]}
{'a': [2, 3], 'b': []}
{'a': [2, 3], 'b': [1]}
{'a': [1, 2, 3], 'b': []}

编辑: 一个更不漂亮但功能强大的版本,允许任意数量的名称:

from itertools import combinations, product

names = ['a', 'b', 'c']
numbers = [1, 2, 3]

perm_list = [list(perm) for perm_len in range(len(numbers)+1) for perm in combinations(numbers, perm_len)]   # generate permutations

name_perm_list = [perm_list for _ in names]

perm_dict = [{names[i]: perms[i] for i in range(len(names))} for perms in product(*name_perm_list) if len(set().union(*perms)) == sum([len(set(perm)) for perm in perms])]   # get all possible non-overlapping combinations

for perm_combination in perm_dict:
    print(perm_combination)

输出:

{'a': [], 'b': [], 'c': []}
{'a': [], 'b': [], 'c': [1]}
{'a': [], 'b': [], 'c': [2]}
{'a': [], 'b': [], 'c': [3]}
{'a': [], 'b': [], 'c': [1, 2]}
{'a': [], 'b': [], 'c': [1, 3]}
{'a': [], 'b': [], 'c': [2, 3]}
{'a': [], 'b': [], 'c': [1, 2, 3]}
{'a': [], 'b': [1], 'c': []}
{'a': [], 'b': [1], 'c': [2]}
{'a': [], 'b': [1], 'c': [3]}
{'a': [], 'b': [1], 'c': [2, 3]}
{'a': [], 'b': [2], 'c': []}
{'a': [], 'b': [2], 'c': [1]}
{'a': [], 'b': [2], 'c': [3]}
{'a': [], 'b': [2], 'c': [1, 3]}
{'a': [], 'b': [3], 'c': []}
{'a': [], 'b': [3], 'c': [1]}
{'a': [], 'b': [3], 'c': [2]}
{'a': [], 'b': [3], 'c': [1, 2]}
{'a': [], 'b': [1, 2], 'c': []}
{'a': [], 'b': [1, 2], 'c': [3]}
{'a': [], 'b': [1, 3], 'c': []}
{'a': [], 'b': [1, 3], 'c': [2]}
{'a': [], 'b': [2, 3], 'c': []}
{'a': [], 'b': [2, 3], 'c': [1]}
{'a': [], 'b': [1, 2, 3], 'c': []}
{'a': [1], 'b': [], 'c': []}
{'a': [1], 'b': [], 'c': [2]}
{'a': [1], 'b': [], 'c': [3]}
{'a': [1], 'b': [], 'c': [2, 3]}
{'a': [1], 'b': [2], 'c': []}
{'a': [1], 'b': [2], 'c': [3]}
{'a': [1], 'b': [3], 'c': []}
{'a': [1], 'b': [3], 'c': [2]}
{'a': [1], 'b': [2, 3], 'c': []}
{'a': [2], 'b': [], 'c': []}
{'a': [2], 'b': [], 'c': [1]}
{'a': [2], 'b': [], 'c': [3]}
{'a': [2], 'b': [], 'c': [1, 3]}
{'a': [2], 'b': [1], 'c': []}
{'a': [2], 'b': [1], 'c': [3]}
{'a': [2], 'b': [3], 'c': []}
{'a': [2], 'b': [3], 'c': [1]}
{'a': [2], 'b': [1, 3], 'c': []}
{'a': [3], 'b': [], 'c': []}
{'a': [3], 'b': [], 'c': [1]}
{'a': [3], 'b': [], 'c': [2]}
{'a': [3], 'b': [], 'c': [1, 2]}
{'a': [3], 'b': [1], 'c': []}
{'a': [3], 'b': [1], 'c': [2]}
{'a': [3], 'b': [2], 'c': []}
{'a': [3], 'b': [2], 'c': [1]}
{'a': [3], 'b': [1, 2], 'c': []}
{'a': [1, 2], 'b': [], 'c': []}
{'a': [1, 2], 'b': [], 'c': [3]}
{'a': [1, 2], 'b': [3], 'c': []}
{'a': [1, 3], 'b': [], 'c': []}
{'a': [1, 3], 'b': [], 'c': [2]}
{'a': [1, 3], 'b': [2], 'c': []}
{'a': [2, 3], 'b': [], 'c': []}
{'a': [2, 3], 'b': [], 'c': [1]}
{'a': [2, 3], 'b': [1], 'c': []}
{'a': [1, 2, 3], 'b': [], 'c': []}

重叠检查非常丑陋,因为我想不出更好的方法来获得多个集合的重叠,因为交集不会削减它。


2
投票

没有 itertools... 对于每个数字,将其附加到任一名称的列表中:

names = ['a', 'b']
numbers = [1, 2, 3]

ds = [{name: [] for name in names}]
for number in numbers:
    ds += [
        {k: v[:] + [number] * (k == name)
         for k, v in d.items()}
        for d in ds
        for name in names
    ]

for d in ds:
    print(d)

输出:

{'a': [], 'b': []}
{'a': [1], 'b': []}
{'a': [], 'b': [1]}
{'a': [2], 'b': []}
{'a': [], 'b': [2]}
{'a': [1, 2], 'b': []}
{'a': [1], 'b': [2]}
{'a': [2], 'b': [1]}
{'a': [], 'b': [1, 2]}
{'a': [3], 'b': []}
{'a': [], 'b': [3]}
{'a': [1, 3], 'b': []}
{'a': [1], 'b': [3]}
{'a': [3], 'b': [1]}
{'a': [], 'b': [1, 3]}
{'a': [2, 3], 'b': []}
{'a': [2], 'b': [3]}
{'a': [3], 'b': [2]}
{'a': [], 'b': [2, 3]}
{'a': [1, 2, 3], 'b': []}
{'a': [1, 2], 'b': [3]}
{'a': [1, 3], 'b': [2]}
{'a': [1], 'b': [2, 3]}
{'a': [2, 3], 'b': [1]}
{'a': [2], 'b': [1, 3]}
{'a': [3], 'b': [1, 2]}
{'a': [], 'b': [1, 2, 3]}
© www.soinside.com 2019 - 2024. All rights reserved.