python - 如何创建一个迭代列表,其中一些变量是独立的,一些是依赖的?
问题描述
我正在尝试列出排列顺序,其中前两个变量和后两个变量之间的顺序很重要,但在这两组之间不重要。我已经能够得到这样的东西:
>>>[p for p in itertools.product([1, 2],[1, 2],[5, 6], [5, 6])]
[(1, 1, 5, 5), (1, 1, 5, 6), (1, 1, 6, 5), (1, 1, 6, 6), (1, 2, 5, 5),
(1, 2, 5, 6), (1, 2, 6, 5), (1, 2, 6, 6), (2, 1, 5, 5), (2, 1, 5, 6),
(2, 1, 6, 5), (2, 1, 6, 6), (2, 2, 5, 5), (2, 2, 5, 6), (2, 2, 6, 5),
(2, 2, 6, 6)]
我想得到一些没有切换顺序重复但保留重复变量的东西,如下所示:
[(1, 1, 5, 5), (1, 1, 5, 6), (1, 1, 6, 6), (1, 2, 5, 5),(1, 2, 5, 6),
(1, 2, 6, 6), (2, 2, 5, 5), (2, 2, 5, 6), (2, 2, 6, 6)]
似乎应该有一种直接的方法来做到这一点,我只是还没有想出它(我主要在 R 中编写代码,并且刚刚开始研究 Python 3)。
解决方案
比使用set
uniquify 的结果更好product
,您可以直接组合product
并itertools.combinations_with_replacement
产生您关心的结果:
from itertools import product, combinations_with_replacement as comb_repl
[p1 + p2 for p1, p2 in product(comb_repl([1, 2], 2), comb_repl([5, 6], 2))]
这会产生所需的准确输出,没有重复(因此不需要单独的重复数据删除步骤)。
请注意,除了传递给 的第一个迭代器之外,所有的迭代器product
都product
将缓存迭代器,因此在这种情况下,完整的输出comb_repl([5, 6], 2)
最终将存储在内存中,以及tuple
您实际需要的所有四个。在这种情况下这很好,但如果您的组合集明显更大,您可能更愿意随时重新计算组合,因此您只需为最终结果支付内存,而不是combinations_with_replacement
为第二个迭代器支付完整的输出集。由于product
缓存,您必须避免它,使用for
重复创建第二个combinations_with_replacement
迭代器的多列表推导:
# Also switched argument to second comb_repl to a tuple, so argument is not repeatedly rebuilt;
# slightly less readable due to profusion of parens, but equivalent behavior
[p1 + p2 for p1 in comb_repl([1, 2], 2) for p2 in comb_repl((5, 6), 2)]
product
在测试中,嵌套循环 listcomp 比在不关心内存时使用稍慢(product
将更多工作推到 C 层,并且只创建两个实例combinations_with_replacement
,而不是第一个迭代器的每个输出加一个;在第二个和随后的传递,它正在迭代tuple
输出的缓存,这与 Python 获得的速度一样快),所以如果你知道你的参数不会变得足够大以至于product
缓存无关紧要,那么 usingproduct
可以获得最佳性能。
在所有情况下,除非你真的需要一个已实现list
的,否则最好使用一个生成器表达式(genexpr),因为一个genexpr 只在被询问时产生结果,并且不必将它们全部存储在内存中;你可以循环一次,然后它就用尽了,但在很多情况下,你只需要循环一次就完成了。使用genexpr,用法如下所示:
# Outer square brackets changed to parentheses
products = (p1 + p2 for p1 in comb_repl([1, 2], 2) for p2 in comb_repl((5, 6), 2))
for p in products:
... do stuff with one output ...
不再复杂,并且对于更大的组合,不会耗尽内存。
推荐阅读
- javascript - 在下一个 js 环境中发送到服务器之前如何处理数据?
- laravel - 如何在刀片模板中删除字符串中的某些字符
- javascript - java.choose 返回无法读取未定义的属性
- c# - 新线程内存使用量不会停止增加
- javascript - 使用网站时:codeforces。我对用户输入感到震惊。如何根据这样的网站构建我的代码?
- javascript - 当我尝试使用 facebook 按钮实现登录时如何避免此错误?
- validation - Google 表格:数据验证 - 跨多列的唯一行值
- python - 损失,准确性,val_loss 没有改变
- java - Spring REST Docs + RequestBody + 防止字段的深层文档
- python - python-docx中的文本格式