生成由动态长度列表组成的动态长度列表
Generating a list of dynamic length consisting of lists of dynamic lengths
我想要一种高效、简洁的方法来在 Python (3.9) 中生成以下子列表列表,这让我很困惑。我敢肯定,对大多数人来说都是儿戏,但我显然只是在婴幼儿游戏中。
变量将是(括号中使用默认值):
- a 是给定子列表 (3) 中的最大条目数
- x 是起始值 (25)
- y为增量值(20)
- z 是最大值 (70)
最后我会添加一个检查,如果 sum(sublist) 在两个变量值之间,子列表仅附加到列表,所以我最终得到满足某些条件的排列列表。这些标准可能包括更改 y 的值以控制迭代的绝对数量。
[
[25],
[45],
[65],
[25,25],
[45,25],
[65,25],
[25,45],
...
[45,65],
[65,65],
[25,25,25],
[45,25,25],
...
[45,65,65],
[65,65,65]
]
您可以对每个长度子集使用 itertools.product()
,然后使用 itertools.chain()
将列表连接在一起。
def get_lists(a, x, y, z, m=float('-inf'), n=float('inf')):
v = list(range(x, z, y))
return list(itertools.chain(*(
(
list(reversed(p))
for p in itertools.product(*([v] * i))
if m < sum(p) < n
) for i in range(1, a + 1)
)))
如果需要,这也可以考虑下限和上限,可选参数 m
和 n
。如果没有给出,那么一切都应该在无穷大和负无穷大之间。
这里使用了一些技巧。
- 首先,
itertools.product()
将以您想要的相反顺序显示(它首先改变最后一个元素,而您首先改变第一个元素)。所以我们将它输入 reversed()
。 itertools.product()
通常也会生成元组而不是列表,但是由于我们必须将迭代器 reversed()
returns 强制转换为列表,所以没有问题。如果你不关心这个,你可以省略最里面的list(reversed(p))
,直接留在p
。或者,如果您根本不关心过滤输入,您可以完全删除内部理解。
- 其次,在
itertools.product()
和 itertools.chain()
中,我们使用参数解包运算符 *
将整个列表作为位置参数传递。对于 itertools.product()
,这只是根据需要多次复制 'eligible values' 范围,而对于 itertools.chain()
,它将每个 itertools.product()
的各个输出拼接在一起。很多itertools滥用都需要这个成语。
否则这只是一些嵌套理解。从技术上讲,您可以在一行中完成,但我发现将 v
放入变量中并执行 [v] * i
比执行 (range(x, z, y) for _ in range(i))
.
更好
我想要一种高效、简洁的方法来在 Python (3.9) 中生成以下子列表列表,这让我很困惑。我敢肯定,对大多数人来说都是儿戏,但我显然只是在婴幼儿游戏中。
变量将是(括号中使用默认值):
- a 是给定子列表 (3) 中的最大条目数
- x 是起始值 (25)
- y为增量值(20)
- z 是最大值 (70)
最后我会添加一个检查,如果 sum(sublist) 在两个变量值之间,子列表仅附加到列表,所以我最终得到满足某些条件的排列列表。这些标准可能包括更改 y 的值以控制迭代的绝对数量。
[
[25],
[45],
[65],
[25,25],
[45,25],
[65,25],
[25,45],
...
[45,65],
[65,65],
[25,25,25],
[45,25,25],
...
[45,65,65],
[65,65,65]
]
您可以对每个长度子集使用 itertools.product()
,然后使用 itertools.chain()
将列表连接在一起。
def get_lists(a, x, y, z, m=float('-inf'), n=float('inf')):
v = list(range(x, z, y))
return list(itertools.chain(*(
(
list(reversed(p))
for p in itertools.product(*([v] * i))
if m < sum(p) < n
) for i in range(1, a + 1)
)))
如果需要,这也可以考虑下限和上限,可选参数 m
和 n
。如果没有给出,那么一切都应该在无穷大和负无穷大之间。
这里使用了一些技巧。
- 首先,
itertools.product()
将以您想要的相反顺序显示(它首先改变最后一个元素,而您首先改变第一个元素)。所以我们将它输入reversed()
。itertools.product()
通常也会生成元组而不是列表,但是由于我们必须将迭代器reversed()
returns 强制转换为列表,所以没有问题。如果你不关心这个,你可以省略最里面的list(reversed(p))
,直接留在p
。或者,如果您根本不关心过滤输入,您可以完全删除内部理解。 - 其次,在
itertools.product()
和itertools.chain()
中,我们使用参数解包运算符*
将整个列表作为位置参数传递。对于itertools.product()
,这只是根据需要多次复制 'eligible values' 范围,而对于itertools.chain()
,它将每个itertools.product()
的各个输出拼接在一起。很多itertools滥用都需要这个成语。
否则这只是一些嵌套理解。从技术上讲,您可以在一行中完成,但我发现将 v
放入变量中并执行 [v] * i
比执行 (range(x, z, y) for _ in range(i))
.