Python:将不同长度的多个列表的子产品合并到元组列表中

时间:2017-07-27 14:44:43

标签: python list itertools

我正在尝试使用以下方法将多个不同长度列表的子产品合并到元组列表中:

import itertools

letters = ['a', 'b', 'c']
symbols = ['*', '#', '+']
numbers = [1, 2, 3, 4, 5]

tuples_of_two = zip(letters, symbols)
tuples_of_three = list(itertools.product(tuples_of_two, numbers))

print(tuples_of_three)

产生包含元组和数字的元组列表:

[(('a', '*'), 1),
 (('a', '*'), 2),
 (('a', '*'), 3),
 (('a', '*'), 4),
 (('a', '*'), 5),
 (('b', '#'), 1),
 (('b', '#'), 2),
 (('b', '#'), 3),
 (('b', '#'), 4),
 (('b', '#'), 5),
 (('c', '+'), 1),
 (('c', '+'), 2),
 (('c', '+'), 3),
 (('c', '+'), 4),
 (('c', '+'), 5)]

但实际上我正在尝试获取以下结果,这是一个没有“子元组”的元组列表:

[('a', '*', 1),
 ('a', '*', 2),
 ('a', '*', 3),
 ('a', '*', 4),
 ('a', '*', 5),
 ('b', '#', 1),
 ('b', '#', 2),
 ('b', '#', 3),
 ('b', '#', 4),
 ('b', '#', 5),
 ('c', '+', 1),
 ('c', '+', 2),
 ('c', '+', 3),
 ('c', '+', 4),
 ('c', '+', 5)]

不是在元组中我只想'a'与'''结合,'b'与'#'和'c'与'+'结合使得它不是intertools.product可以达到的完整产品

这可以通过使用一些列表理解来实现,这些列表理解“解开”元组的第一个元素,或者在直接的方式上更优雅。

但我现在卡住了..

有人可以帮忙吗?

提前致谢!

5 个答案:

答案 0 :(得分:2)

itertools.product与嵌套的for循环做同样的事情。您可以使用zip的直接列表理解来一次性实现所需:

[(l, s, n) for l, s in zip(letters, symbols) for n in numbers]

#[('a', '*', 1),
# ('a', '*', 2),
# ('a', '*', 3),
# ('a', '*', 4),
# ('a', '*', 5),
# ('b', '#', 1),
# ...

答案 1 :(得分:2)

你可以通过构建一个将内部元素添加到单个元组中的新元素来展平元组:

tuples_of_three =  [x+(y,) for x, y in itertools.product(tuples_of_two, numbers)]

答案 2 :(得分:1)

摘自itertools.product()文档:

  

产品(A,B)返回相同的:((x,y)对于A中的x,对于B中的y)

因此,您可以这样做:

letters = ['a', 'b', 'c']
symbols = ['*', '#', '+']
numbers = [1, 2, 3, 4, 5]

print([(letter, symbol, number) for letter, symbol in zip(letters, symbols) for number in numbers])

答案 3 :(得分:0)

一种有点“一般”的解决方案,使用zip(numbers)来包装元组中的数字。然后你统一只有元组,它们可以简单地求和。

>>> if 1:
    import itertools, pprint

    letters = ['a', 'b', 'c']
    symbols = ['*', '#', '+']
    numbers = [1, 2, 3, 4, 5]
    zips = zip(letters, symbols), zip(numbers)

    result = [sum(p, ()) for p in itertools.product(*zips)]

    pprint.pprint(result)


[('a', '*', 1),
 ('a', '*', 2),
 ('a', '*', 3),
 ('a', '*', 4),
 ('a', '*', 5),
 ('b', '#', 1),
 ('b', '#', 2),
 ('b', '#', 3),
 ('b', '#', 4),
 ('b', '#', 5),
 ('c', '+', 1),
 ('c', '+', 2),
 ('c', '+', 3),
 ('c', '+', 4),
 ('c', '+', 5)]
>>> 

这也适用于更复杂的组合,您只需要定义它们,例如:

    zips = zip(letters, symbols), zip(numbers), zip(symbols, letters, numbers)

如果你有更多/更长的元组,那么它们可能更有效:

    result = [tuple(itertools.chain.from_iterable(p))
              for p in itertools.product(*zips)]

答案 4 :(得分:-1)

tuples_of_three = list(itertools.product(letters, symbols, numbers))

它应该适合你:

('a', '*', 1)
('a', '*', 2)
('a', '*', 3)
('a', '*', 4)
('a', '*', 5)
('a', '#', 1)
('a', '#', 2)
('a', '#', 3)
('a', '#', 4)
('a', '#', 5)
('a', '+', 1)
('a', '+', 2)
('a', '+', 3)
('a', '+', 4)
('a', '+', 5)
('b', '*', 1)
('b', '*', 2)
('b', '*', 3)
('b', '*', 4)
('b', '*', 5)
('b', '#', 1)
('b', '#', 2)
...