python - Python - 将不同值的组合计算为总和
问题描述
给定一个元组列表如下:
values = [
('a', 'b', 'c'),
('d', 'e'),
('f', 'g', 'h')
]
我想计算这些值的不同组合,但不是作为笛卡尔积,而是作为一些自定义规则的总和。澄清一下,如果我们计算这些元组之间的笛卡尔积,我们将得到 3*2*3 = 18 种不同的组合。但我的愿望是得到这样的东西:
combinations = [
('a', 'd', 'f'),
('a', 'e', 'g'),
('a', 'e', 'h'),
('b', 'd', 'f'),
('b', 'e', 'g'),
('b', 'e', 'h'),
('c', 'd', 'f'),
('c', 'e', 'g'),
('c', 'e', 'h')
]
所以结果列表包含 9 种不同的组合,而不是 18 种。带有 4 个元组的示例:
values = [
('a', 'b', 'c'),
('d', 'e'),
('f', 'g', 'h'),
('i', 'j', 'k', 'l')
]
结果将是
combinations = [
('a', 'd', 'f', 'i'),
('a', 'e', 'g', 'j'),
('a', 'e', 'h', 'k'),
('a', 'e', 'h', 'l'),
('b', 'd', 'f', 'i'),
('b', 'e', 'g', 'j'),
('b', 'e', 'h', 'k'),
('b', 'e', 'h', 'l'),
('c', 'd', 'f', 'i'),
('c', 'e', 'g', 'j'),
('c', 'e', 'h', 'k'),
('c', 'e', 'h', 'l'),
]
进一步解释输出的逻辑:
在这两个输入中,第一个元组的行为就像在笛卡尔积中一样。但是,除了第一个元组之外的所有其他元组都被迭代(或压缩)在一起。此外,如果一个被迭代在一起的元组可以这么说“用完值”,我们将使用元组中的最后一个值。
实现这一目标的有效方法是什么?
解决方案
通过提供的额外示例,我们可以弄清楚逻辑的外观。本质上,第一行被特殊处理并用于正常的“笛卡尔积”。
然而,其余的行被有效地延伸到最大长度,并被拉在一起。对其进行编码,它可能如下所示:
from itertools import product
def extend_to_max_len(tup, length):
'''extends a tuple to a specified length by
filling the empty spaces with last element of given tuple
'''
fill_count = length - len(tup)
return (*tup, *[tup[-1]]*fill_count)
def non_cartesian_sum(values):
'''Expects a list of tuples.
gives the output according to the custom rules:
top: first row: to be used for cartesian product with zip of remaining rows
bottom: remaining rows: extended to longest length before zipping
'''
if len(values) < 2:
print("Check length of input provided")
return None
top = values[0]
bottom = values[1:]
max_len = max(len(row) for row in bottom)
bottom = [extend_to_max_len(row, max_len) for row in bottom]
out = [(first, *rest) for first, rest in product(top, zip(*bottom))]
return out
values = [
('a', 'b', 'c'),
('d', 'e'),
('f', 'g', 'h'),
('i', 'j', 'k', 'l')
]
out = non_cartesian_sum(values)
print(out)
输出:
[('a', 'd', 'f', 'i'),
('a', 'e', 'g', 'j'),
('a', 'e', 'h', 'k'),
('a', 'e', 'h', 'l'),
('b', 'd', 'f', 'i'),
('b', 'e', 'g', 'j'),
('b', 'e', 'h', 'k'),
('b', 'e', 'h', 'l'),
('c', 'd', 'f', 'i'),
('c', 'e', 'g', 'j'),
('c', 'e', 'h', 'k'),
('c', 'e', 'h', 'l')]
请注意,在将此功能用于您的用例之前,您可能希望根据需要添加更多输入验证。
推荐阅读
- javascript - 通过插件在管理头中添加脚本
- google-chrome-devtools - 什么是 Google Chrome 检查器?
- javascript - 填写一个日历月的空白块
- javascript - 如何在 node.js 中以编程方式插入 jsdoc @param
- rust - 不匹配的类型错误:预期的 `char`,找到参考
- c++ - 未处理的异常 C++ SFML
- python - 多选表单和查询 django
- c# - JSON Schema 条件结果
- apache - 带有两个正斜杠(不是双斜杠)的 Htaccess 重定向 URL 将不起作用
- javascript - Gulp watch 不看 .js 文件