python - 在Python中生成特定的列表组合

标签 python python-3.x permutation python-itertools

我有 2 个不同长度的列表,例如:

list_a = ['a', 'b', 'c', 'd']
list_b = ['x', 'y']

我想要的输出是list_b到list_a的所有唯一组合,例如应该有16个:

1. ['a', 'x', 'y']
2. [['a', 'x'], ['b', 'y']]
3. [['a', 'x'], ['c', 'y']]
4. [['a', 'x'], ['d', 'y']]
5. ['b', 'x', 'y']
6. [['b', 'x'], ['a', 'y']]
7. [['b', 'x'], ['c', 'y']]
8. [['b', 'x'], ['d', 'y']]
9. ['c', 'x', 'y']
10. [['c', 'x'], ['a', 'y']]
11. [['c', 'x'], ['b', 'y']]
12. [['c', 'x'], ['d', 'y']]
13. ['d', 'x', 'y']
14. [['d', 'x'], ['a', 'y']]
15. [['d', 'x'], ['b', 'y']]
16. [['d', 'x'], ['c', 'y']]

我对总列表数量的猜测是 len(list_a) ** len(list_b),所以我知道选项空间很快就会变得非常大。

关于在 Python 中执行此操作的有效方法的任何建议(避免生成过多的排列和测试重复项等)/

我在许多不同的列表类型和构成上使用了 itertools 产品、排列和组合。我可以通过使用循环查找所有答案来生成所需的答案,其中每个 list_a 有来自 list_b 的 2 个条目(即上面的 1、5、9、13),然后找到每个 list_a 有来自 list_b 的 1 个条目的所有组合,但是此方法一旦 len(list_b) > 2 就会掉落。

编辑: 这是一个源/汇问题。 list_b 是所有需要完全使用的接收器,list_a 是可以向接收器提供输入的源。即,对于上述问题,所有 3 个接收器都可以由单个源提供服务(示例 1、5、9、13),或者可以通过多种方式拆分 1 个源 -> 2 个接收器,或 1:1 - I'我试图找到所有这些方法

最佳答案

您似乎想要一个从 list_blist_a 的所有函数的列表,但您希望每个函数都以特定的形式表示列表形式而不是通常的 dict 形式或有序对形式。 “函数”这个词比“组合”这个词更适合这里。

您的函数格式有两个特点。首先,示例所需输出中的大多数行都是列表的列表。但是,如果所表示的函数将图像(list_a 中的结果项)仅作为 list_a 的一个元素,那么您将获得一个列表,而不是列表的列表。这在您的示例中有效,其中 list_b 中只有两项,因此函数的范围是 list_a 中的一项或所有项目。但是,如果 list_b 较大,则可能会出现范围既不是 list_a 中的一项也不是所有项的情况,并且您对该行所需的结果不清楚。

其次,您的行的顺序与此类事物的通常顺序并不最佳匹配。

这里的代码给出了所有行的列表列表,并且顺序与您给出的顺序略有不同。基本思想是通过按固定顺序排列域 list_b 中的项目来获得一个函数,由于数据结构是一个列表,所以这已经完成了。然后获取list_aproduct(在itertools意义上),使用repeat=len(list_b),这样product中的第一项是list_b中第一项的函数结果,依此类推。例程的其余部分将此定义的函数转换为其反函数的字典形式,该函数将每个结果项与映射到它的所有域项分组,然后将其转换为您显示的列表格式。

from itertools import product
from collections import defaultdict


def functions_as_lists(tolist, fromlist):
    """Return a list of functions from fromlist to tolist where each
    function is represented as a list of lists.
    """
    result = []
    for toitems in product(tolist, repeat=len(fromlist)):
        # Convert a tuple to a function represented as a dict
        afunction = defaultdict(list)
        for toitem, fromitem in zip(toitems, fromlist):
            afunction[toitem].append(fromitem)
        # Convert the dict-function to the desired list of lists
        alist = [[toitem] + fromitems
                 for toitem, fromitems in afunction.items()]
        # Store that list form of the function
        result.append(alist)
    return result


for item in functions_as_lists(['a', 'b', 'c', 'd'], ['x', 'y']):
    print(item)

输出是:

[['a', 'x', 'y']]
[['a', 'x'], ['b', 'y']]
[['a', 'x'], ['c', 'y']]
[['a', 'x'], ['d', 'y']]
[['b', 'x'], ['a', 'y']]
[['b', 'x', 'y']]
[['b', 'x'], ['c', 'y']]
[['b', 'x'], ['d', 'y']]
[['c', 'x'], ['a', 'y']]
[['c', 'x'], ['b', 'y']]
[['c', 'x', 'y']]
[['c', 'x'], ['d', 'y']]
[['d', 'x'], ['a', 'y']]
[['d', 'x'], ['b', 'y']]
[['d', 'x'], ['c', 'y']]
[['d', 'x', 'y']]

我的代码使用 defaultdict,它在 CPython 3.7 中保留顺序。在其他发行版中可能并非如此,因此我的代码可能会导致与上面的输出稍有不同的行。 Python 3.6 及更高版本中更复杂的代码可以使用常规的 dict 而不是 defaultdict 来解决这个问题。

注意:如果您确实希望第一行是 ['a', 'x', 'y'] 而不是 [['a', 'x', ' y']],您可以在定义变量 alist 的行后面添加这两行:

if len(alist) == 1:
    alist = alist[0]

但这可能不是您想要的 list_a 较长值。

关于python - 在Python中生成特定的列表组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57192675/

相关文章:

algorithm - 可证明正确的排列小于 O(n^2)

python - 如何解决六角形图中的边缘问题?

python - 从列中删除多余的字符或值

python-3.x - 使用 tor 发出请求 python?

arrays - 在没有 for 循环的情况下查找数组的排列

python - 向排列添加约束

python - Flask-admin 不强制执行外键约束

python - 在循环内逐列修改numpy数组

python - pymysql如何为存储过程传递参数

python - 类型错误 : cannot convert the series to <class 'float' >