我在Python中有一个地图列表,如下所示:
2: a, b
3: b, c, d
4: a
我想创建键值对的所有组合,即:
(2,a)(3,b)(4,a)
(2,a)(3,c)(4,a)
(2,a)(3,d)(4,a)
(2,b)(3,b)(4,a)
(2,b)(3,c)(4,a)
(2,b)(3,d)(4,a)
我既不知道地图的大小也不知道列表的大小,但列表永远不会有超过4个元素。我可以假设密钥是唯一的,但并不是它们总是1,2,3,4或0,1,2,3,如上例所示。
解决这个问题的最聪明/最有效的方法是什么?
答案 0 :(得分:3)
假设你" dict的列表"使用此格式{2: ["a", "b"], 3: ["b", "c", "d"], 4: ["a"]}
(已确认为in comments),您可以先使用列表推导来获取所有可能的键值对,然后使用itertools.product
获取组合那些对。
>>> d = {2: ["a", "b"], 3: ["b", "c", "d"], 4: ["a"]}
>>> pairs = [[(k, v) for v in d[k]] for k in d]
>>> list(itertools.product(*pairs))
[((2, 'a'), (3, 'b'), (4, 'a')),
((2, 'a'), (3, 'c'), (4, 'a')),
((2, 'a'), (3, 'd'), (4, 'a')),
((2, 'b'), (3, 'b'), (4, 'a')),
((2, 'b'), (3, 'c'), (4, 'a')),
((2, 'b'), (3, 'd'), (4, 'a'))]
使用您的"实际"例如:
>>> d = {(8, 5): set(['Mt Everest', 'Mt Blanc']), (11, 5): set(['K2'])}
>>> pairs = [[(k, v) for v in d[k]] for k in d]
>>> list(itertools.product(*pairs))
[(((8, 5), 'Mt Everest'), ((11, 5), 'K2')),
(((8, 5), 'Mt Blanc'), ((11, 5), 'K2'))]
答案 1 :(得分:1)
首先看基础案例。如果只有一个地图2, a, b
,则解决方案为
initial_sol = (2,a)
(2,b)
如果我现在再添加一张地图3, b, c, d
通过将新映射中的每个元组附加到先前的解决方案
second_sol = (2,a)(3,b)
(2,a)(3,c)
(2,a)(3,d)
(2,b)(3,b)
(2,b)(3,c)
(2,b)(3,d)
现在假设我已经有一个程序为一组给定的地图解决这个问题,通过使用新添加的地图扩展解决方案,可以解决更大地图的问题
import itertools
# supose the maps you want to solve are in this format
themaps=[[2,'a','b'],[3,'b','c','d'],[4,'a']]
# a little work is required to reformat its structure
themaps=list(map(lambda x: list(map(lambda y: (x[0], y), x[1:])),themaps))
def flatmap(func, *iterable):
return itertools.chain.from_iterable(map(func, *iterable))
# method of appending each element from the newly added map to current solutions
# in order to extend the old solutions to new solutions of larger maps
def next_solution(sol, anewmap):
return list(flatmap(lambda x: map(lambda y: x+[y], anewmap), sol))
# a reduced set of maps
def smaller(M): return M[0:-1]
# newly added map
def newmap(M): return M[-1]
# solutions at base case
def base_solution(M): return [[i] for i in M[0]]
# function to solve the problem with any given set of maps
# Notice how this reduces the problem of solving larger maps to smaller maps
def solve_it(allmaps):
if allmaps == []:
return []
elif len(allmaps) == 1:
return base_solution(allmaps)
else:
return next_solution(solve_it(smaller(allmaps)), newmap(allmaps))
print(solve_it(themaps))
答案 2 :(得分:0)
最后想出了一个算法 - 这里是伪代码:
function comb_map(list)
if list is empty
return empty list
else
current_element = list.pop()
result_list = empty list
for each element in current_list.values #call it: b
for each element in comb_map(list) #call it: as
add b to as
add as to result_list
return result_list