![](/img/trans.png)
[英]How to get all permutations of string as list of strings (instead of list of tuples)?
[英]How to create all permutations of a list of tuples depending on one boolean field keeping order in Python
假设我有一个输入作为这样的元组列表:
[('a', True),
('b', False),
('c', True),
('d', False)]
每个具有True
作为第二个参数的元组都被认为是可选的。
现在,我想通过以下方式置换此结构:
False
元组不变(消失) 因此,以上示例的输出应如下所示:
[[('a', True),
('b', False),
('c', True),
('d', False)],
[('b', False),
('c', True),
('d', False)],
[('a', True),
('b', False),
('d', False)],
[('b', False),
('d', False)]]
有什么想法如何以一种优雅的方式解决这个问题? 我尝试递归,但无法完成。
我不确定是否有特别优雅的方法。 从概念上讲,您需要计算可选元素的功效集,然后以满足您要求的方式将其与非可选元素合并。 这是一种方法:
import itertools
a = [('a', True), ('b', False), ('c', True), ('d', False)]
optional_count = sum(optional for x, optional in a)
for include in itertools.product([True, False], repeat=optional_count):
include_iter = iter(include)
print([
(x, optional)
for x, optional in a
if not optional or next(include_iter)
])
印花
[('a', True), ('b', False), ('c', True), ('d', False)]
[('a', True), ('b', False), ('d', False)]
[('b', False), ('c', True), ('d', False)]
[('b', False), ('d', False)]
该循环遍历所有元组,指示是否包括可选元素:
True, True
True, False
False, True
False, False
打印语句中的列表理解包括所有非可选元素,对于可选元素,请查看include
中的下一个可用元素。
实际上,我刚刚想到了一个不错的递归解决方案:
def choices(a):
if not a:
yield []
return
head, *tail = a
if head[1]:
yield from choices(tail)
for tail_choice in choices(tail):
yield [head] + tail_choice
这会在所有元组列表上创建一个惰性生成器:
>>> list(choices(a))
[[('b', False), ('d', False)],
[('b', False), ('c', True), ('d', False)],
[('a', True), ('b', False), ('d', False)],
[('a', True), ('b', False), ('c', True), ('d', False)]]
您可以通过复制到目前为止的选择列表来做出选择,然后将新值附加到副本中,然后将其与到目前为止的选择列表合并。
很抱歉得到这个可怕的解释,但是我现在无法提出更好的建议。 如果可以提出更好的建议,请随时进行编辑。 否则,我希望下面的图表和代码可以更好地解释我的解决方案。
[]
-------------------------------------------
[] [0]
---------------------------- ---------------------------
[] [1] [0] [0, 1]
... ... ... ...
基本思想是遍历所有项目,克隆所有部分解决方案,然后将项目追加到克隆的解决方案中。
def choose(arr):
res = [[]]
for t in arr:
if t[1]:
# make a copy of all found solutions
clone = [list(c) for c in res]
# append the new value to the original solutions
for l in res:
l.append(t)
# merge solution-list with the list of copies
res += clone
else:
# non-optional element => just add the element to all solutions
for l in res:
l.append(t)
return res
输出:
print('\n'.join(str(l) for l in choose([('a', True), ('b', False), ('c', True), ('d', False)])
[('a',True),('b',False),('c',True),('d',False)]
[('b',False),('c',True),('d',False)]
[('a',True),('b',False),('d',False)]
[('b',False),('d',False)]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.