我需要一种方法来查找两个不同列表中的所有组合,其中每个元素可能为空,也可能不为空。例如,对于这两个列表,我想调用一个函数来返回所有这些组合的列表:
a = ['A', 'S', 'B']
b = ['A', 'B']
find_combinations(a, b)
应该返回:
[['A', 'S', 'B'], ['A', 'S'], ['S', 'B'], ['S']]
我可以做这个简单的例子但是如果列表更复杂说['A', 'B', 'S', 'A', 'A']
那么可能的选项要复杂得多:
[['A', 'B', 'S', 'A', 'A'],
['A', 'B', 'S', 'A'],
['A', 'B', 'S', 'A'],
['B', 'S', 'A', 'A']
... etc.
答案 0 :(得分:2)
我将假设b
的元素可以播放。在这种情况下,您可以使用以下代码:
def without(a,i,bi,l):
if i >= len(a):
yield tuple(l)
else:
l.append(a[i])
for result in without(a,i+1,bi,l):
yield result
l.pop()
if a[i] in bi:
for result in without(a,i+1,bi,l):
yield result
def find_combinations(a, b):
for result in without(a,0,set(b),[]):
yield result
我们首先将b
转换为一组以提升效果。严格来说,这不是必要的。然后我们使用递归算法,对于a[i]
中的a
中的每个元素b
,我们有一个决策点是否要将其包含在结果中(这就是我们执行的原因)弹出该元素时再次递归)。当我们到达列表末尾时,我们会将运行列表l
转换为tuple(..)
。您还可以使用list(..)
将其转换为列表。
我们使用运行列表来提升性能,因为在 O(n)中连接两个列表,而中的运行列表可以append(..)
和pop(..)
> O(1)摊销成本。
这将生成tuple
s 的生成器。您可以使用list(..)
来实现每个生成器的结果,如:
>>> list(find_combinations(['A','S','B'],['A','B']))
[('A', 'S', 'B'), ('A', 'S'), ('S', 'B'), ('S',)]
>>> list(find_combinations(['A', 'B', 'S', 'A', 'A'],['A','B']))
[('A', 'B', 'S', 'A', 'A'), ('A', 'B', 'S', 'A'), ('A', 'B', 'S', 'A'), ('A', 'B', 'S'), ('A', 'S', 'A', 'A'), ('A', 'S', 'A'), ('A', 'S', 'A'), ('A', 'S'), ('B', 'S', 'A', 'A'), ('B', 'S', 'A'), ('B', 'S', 'A'), ('B', 'S'), ('S', 'A', 'A'), ('S', 'A'), ('S', 'A'), ('S',)]
如果需要list
,您可以使用map(list,..)
将其转换为列表,例如:
>>> list(map(list,find_combinations(['A','S','B'],['A','B'])))
[['A', 'S', 'B'], ['A', 'S'], ['S', 'B'], ['S']]
>>> list(map(list,find_combinations(['A', 'B', 'S', 'A', 'A'],['A','B'])))
[['A', 'B', 'S', 'A', 'A'], ['A', 'B', 'S', 'A'], ['A', 'B', 'S', 'A'], ['A', 'B', 'S'], ['A', 'S', 'A', 'A'], ['A', 'S', 'A'], ['A', 'S', 'A'], ['A', 'S'], ['B', 'S', 'A', 'A'], ['B', 'S', 'A'], ['B', 'S', 'A'], ['B', 'S'], ['S', 'A', 'A'], ['S', 'A'], ['S', 'A'], ['S']]
答案 1 :(得分:0)
在玩完之后,我找到了Willem Van Onsem回答的另一种方法。不太干净但也有效。
def empty_derivations(rule, empty_list):
returned = []
returned.append(rule)
for element in returned:
for num, char in enumerate(element):
temp = element[:]
if char in empty_list:
del temp[num]
returned.append(temp)
return_list = []
for element in returned:
if element not in return_list:
return_list.append(element)
return return_list
当被叫时:
>>> a = empty_derivations(['A', 'B', 'S', 'A', 'A'], ['A', 'B'])
>>> print(a)
[['A', 'B', 'S', 'A', 'A'],
['B', 'S', 'A', 'A'],
['A', 'S', 'A', 'A'],
['A', 'B', 'S', 'A'],
['S', 'A', 'A'],
['B', 'S', 'A'],
['A', 'S', 'A'],
['A', 'B', 'S'],
['S', 'A'],
['B', 'S'],
['A', 'S'],
['S']]