【问题标题】:Python getting unique pairs from multiple lists of different lengthsPython从不同长度的多个列表中获取唯一对
【发布时间】:2016-05-18 04:21:54
【问题描述】:

假设在 Python 中我有 3 个列表:a, b, c 的可变长度。例如:

a=[1,2,3]
b=[4,5,6]
c=[7,8]

我想获得上面 3 个列表中两个元素的每个唯一组合,即。 e.

[1,4],[1,5],[1,6],[1,7],[1,8],[2,4],[2,5]... 并且不是 3 个列表的唯一组合(例如 [1,4,7],[1,4,8],...)。

我已经使用itertools 查看了solution here,这对于 2 个列表来说非常好;但是,当包含 nth 列表时,此解决方案不再适用,因为唯一组合的长度为 n。

这是我尝试过的:

import itertools

a=[1,2,3]
b=[4,5,6]
c=[7,8]

d=list(itertools.product(a,b,c))

[(1, 4, 7), (1, 4, 8), (1, 5, 7), (1, 5, 8), (1, 6, 7), (1, 6, 8), (2, 4, 7), (2, 4, 8), (2, 5, 7), (2, 5, 8), (2, 6, 7), (2, 6, 8), (3, 4, 7), (3, 4, 8), (3, 5, 7), (3, 5, 8), (3, 6, 7), (3, 6, 8)]

注意:以上只是一个示例,该解决方案应该适用于可变长度的n 列表,并且可能在不同的列表中具有相同的值...任何关于我如何做的想法将不胜感激! :)


编辑:正如@SirParselot 所问,元素必须来自不同的列表

【问题讨论】:

  • 你试过什么?
  • 组合必须在不同的列表之间吗?
  • FWIW,我的答案适用于原始问题,具有任意数量的输入列表。但是“冗余元素”到底是什么意思?
  • @PM2Ring 编辑完成!只要我没有在不同列表中出现两次(或更多)相同的值,您的解决方案似乎确实可以正常工作:)
  • @tlorin:Pynchia 在脚本顶部执行import itertools as it。我会在我的答案中添加一些代码。

标签: python list itertools


【解决方案1】:

你想要(a, b, c)中每对列表的Cartesian product,所以首先你需要itertools.combinations来生成列表对,然后itertools.product来创建所需的输出元组。

from itertools import combinations, product

def pairs(*lists):
    for t in combinations(lists, 2):
        for pair in product(*t):
            yield pair

a = [1, 2, 3]
b = [4, 5, 6]
c = [7, 8]

for pair in pairs(a, b, c):
    print(pair)

输出

(1, 4)
(1, 5)
(1, 6)
(2, 4)
(2, 5)
(2, 6)
(3, 4)
(3, 5)
(3, 6)
(1, 7)
(1, 8)
(2, 7)
(2, 8)
(3, 7)
(3, 8)
(4, 7)
(4, 8)
(5, 7)
(5, 8)
(6, 7)
(6, 8)

这是一个处理重复元素的新版本。如果元组中的两个项目彼此相等,它不会返回元组,并且它还通过将来自pairs 的输出馈送到一个集合中来消除输出中的重复元组。这是相当有效的,因为pairs 是一个生成器,因此在找到重复项时会消除它们。

from itertools import combinations, product

def pairs(*lists):
    for t in combinations(lists, 2):
        for pair in product(*t):
            #Don't output pairs containing duplicated elements 
            if pair[0] != pair[1]:
                yield pair

a = [1, 2, 3]
b = [3, 4, 5]
c = [5, 6]

#Feed the output of `pairs` into a set to eliminate duplicate tuples
output = set(pairs(a, b, c))
for pair in sorted(output):
    print(pair)

输出

(1, 3)
(1, 4)
(1, 5)
(1, 6)
(2, 3)
(2, 4)
(2, 5)
(2, 6)
(3, 4)
(3, 5)
(3, 6)
(4, 5)
(4, 6)
(5, 6)

【讨论】:

  • 很抱歉再次打扰您:如果我有一个 UNKNOWN 大小 n 的列表列表(在您的解决方案中,大小是 3,我们从一开始就知道它是 3)?例如,如果我有一个列表列表(带有n 列表)作为字典值,我想做类似output = set(pairs(dict[value])) 的事情,但这似乎不起作用......例如:dict = {'value': [[2,1],[3,3]]};output = set(pairs(dict['value']));output 给出:@987654338 @。我认为这与您的解决方案有关,所以我在这里作为评论提出,但如果您愿意,我可以发表新帖子:)
  • 我的pairs 函数可以处理任何 个输入列表(或元组),例如您可以使用output = set(pairs(a,b,c,d,e)),其中a,b,等等,是简单的列表或元组。如果你想向它传递一个列表列表(或一个元组的元组等),你需要使用*“splat”运算符,它将一个列表(或元组)转换为单独的参数。例如:mylists=[[2,1],[3,3]];output = set(pairs(*mylists))。或者使用您的示例,output = set(pairs(*dct['value']))。 (我将您的字典名称更改为dct,因为使用dict、list、str 等作为变量名是不好的做法。
  • 我错过了*!很方便,我不知道这个!好吧,再次非常感谢:)
  • 没问题! Splat 非常方便。还有双 splat ** 对字典做类似的事情。见stackoverflow.com/q/36901/4014959
【解决方案2】:

我想你应该做的是使用两个列表的工作解决方案来使用n 列表。基本上,您可以将输入转换为列表列表,然后执行以下操作:

for index, left_list in enumerate(list_of_lists):
        other_lists = (list_of_lists[0:index] + list_of_lists[index+1:])
        right_list = [i for sublist in other_lists for i in sublist]
        print(list(itertools.product(left_list, right_list)))

【讨论】:

  • 根据需要使用 yield/yield from 将此算法放入子函数中。
猜你喜欢
  • 1970-01-01
  • 2020-02-06
  • 1970-01-01
  • 2015-02-11
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-27
相关资源
最近更新 更多