字典的不同键的连接 Python (递归?)

Concatenation of a variant number of keys of a dictionary Python (recursion?)

大家好 Stackoverlow 会员,

我正在尝试连接字典的键(字符串)和值(列表)。

为了让您更好地理解,这里是我开头的内容:

dict = {'bk1':
            {'k11': ['a1', 'b1', 'c1'],
             'k12': ['a2', 'b2', 'c2']},
        'bk2':
            {'k21': ['d1', 'e1'],
             'k22': ['d2', 'e2'],
             'k23': ['d3', 'e3']},
        'bk3':
            {'k31': ['f1', 'g1', 'h1'],
             'k32': ['f2', 'g2', 'h2']}
        }

这是我最后想要的:

newdict = {'k11_k21_k31': ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1'],
           'k11_k21_k32': ['a1', 'b1', 'c1', 'd1', 'e1', 'f2', 'g2', 'h2'],
           'k11_k22_k31': ['a1', 'b1', 'c1', 'd2', 'e2', 'f1', 'g1', 'h1'],
           'k11_k22_k32': ['a1', 'b1', 'c1', 'd2', 'e2', 'f2', 'g2', 'h2'],
           'k11_k23_k31': ['a1', 'b1', 'c1', 'd3', 'e3', 'f1', 'g1', 'h1'],
           'k11_k23_k32': ['a1', 'b1', 'c1', 'd3', 'e3', 'f2', 'g2', 'h2'],
           'k12_k21_k31': ['a2', 'b2', 'c2', 'd1', 'e1', 'f1', 'g1', 'h1'],
           'k12_k21_k32': ['a2', 'b2', 'c2', 'd1', 'e1', 'f2', 'g2', 'h2'],
           'k12_k22_k31': ['a2', 'b2', 'c2', 'd2', 'e2', 'f1', 'g1', 'h1'],
           'k12_k22_k32': ['a2', 'b2', 'c2', 'd2', 'e2', 'f2', 'g2', 'h2'],
           'k12_k23_k31': ['a2', 'b2', 'c2', 'd3', 'e3', 'f1', 'g1', 'h1'],
           'k12_k23_k32': ['a2', 'b2', 'c2', 'd3', 'e3', 'f2', 'g2', 'h2']}

我希望这样做:

"bk3" 被遗漏的地方。

我尝试使用叠层 "for" 循环,但循环的数量取决于 "big keys"...

的数量

然后,我觉得这个问题可以用递归来解决(也许?),但是尽管我进行了研究并愿意实现它,但我还是失败了。

任何有关 "recursive or not" 解决方案的帮助将不胜感激。

谢谢,

垫子


哇哦,反应真好! 非常感谢您所有的快速回答,它工作 完美!

正如@jksnw 在评论中所建议的那样,您可以使用 itertools.product 来执行此操作:

import itertools

dct = {
    'bk1': {
        'k11': ['a1', 'b1', 'c1'],
        'k12': ['a2', 'b2', 'c2']
    },
    'bk2':{
        'k21': ['d1', 'e1'],
        'k22': ['d2', 'e2'],
        'k23': ['d3', 'e3']
    },
    'bk3': {
        'k31': ['f1', 'g1', 'h1'],
        'k32': ['f2', 'g2', 'h2']
    }
}

big_keys = dct.keys()
small_keys = (dct[big_key].keys() for big_key in big_keys)

res = {}
for keys_from_each in itertools.product(*small_keys):
    key = "_".join(keys_from_each)

    value = []
    for big_key, small_key in zip(big_keys, keys_from_each):
        value.extend(dct[big_key][small_key])

    res[key] = value

这样:

>>> res

{'k11_k21_k31': ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1'],
 'k11_k21_k32': ['a1', 'b1', 'c1', 'd1', 'e1', 'f2', 'g2', 'h2'],
 'k11_k22_k31': ['a1', 'b1', 'c1', 'd2', 'e2', 'f1', 'g1', 'h1'],
 'k11_k22_k32': ['a1', 'b1', 'c1', 'd2', 'e2', 'f2', 'g2', 'h2'],
 'k11_k23_k31': ['a1', 'b1', 'c1', 'd3', 'e3', 'f1', 'g1', 'h1'],
 'k11_k23_k32': ['a1', 'b1', 'c1', 'd3', 'e3', 'f2', 'g2', 'h2'],
 'k12_k21_k31': ['a2', 'b2', 'c2', 'd1', 'e1', 'f1', 'g1', 'h1'],
 'k12_k21_k32': ['a2', 'b2', 'c2', 'd1', 'e1', 'f2', 'g2', 'h2'],
 'k12_k22_k31': ['a2', 'b2', 'c2', 'd2', 'e2', 'f1', 'g1', 'h1'],
 'k12_k22_k32': ['a2', 'b2', 'c2', 'd2', 'e2', 'f2', 'g2', 'h2'],
 'k12_k23_k31': ['a2', 'b2', 'c2', 'd3', 'e3', 'f1', 'g1', 'h1'],
 'k12_k23_k32': ['a2', 'b2', 'c2', 'd3', 'e3', 'f2', 'g2', 'h2']}

这里,itertools.product 用于获取我们从每个块中取出的 "small keys" 的列表:

>>> big_keys = dct.keys()
>>> small_keys = (dct[big_key].keys() for big_key in big_keys)
>>> list(itertools.product(*small_keys))

[('k12', 'k22', 'k31'),
 ('k12', 'k22', 'k32'),
 ('k12', 'k23', 'k31'),
 ('k12', 'k23', 'k32'),
 ('k12', 'k21', 'k31'),
 ('k12', 'k21', 'k32'),
 ('k11', 'k22', 'k31'),
 ('k11', 'k22', 'k32'),
 ('k11', 'k23', 'k31'),
 ('k11', 'k23', 'k32'),
 ('k11', 'k21', 'k31'),
 ('k11', 'k21', 'k32')]

您可以使用 itertools.productreduce(lambda x,y:x+y,i) 来展平您的嵌套列表,也不要使用 dict 或其他 python 内置类型名称或关键字作为您的变量名称(我使用 d):

>>> from itertools import product
>>> v=[i.values() for i in d.values()]
>>> v=[reduce(lambda x,y:x+y,i) for i in product(*v)]
>>> k=[i.keys() for i in d.values()]
>>> k=['_'.join(i) for i in product(*k)]
>>> {k:v for k,v in zip(k,v)}
{'k31_k12_k22': ['f1', 'g1', 'h1', 'a2', 'b2', 'c2', 'd2', 'e2'], 
 'k32_k12_k21': ['f2', 'g2', 'h2', 'a2', 'b2', 'c2', 'd1', 'e1'],         
 'k31_k11_k22': ['f1', 'g1', 'h1', 'a1', 'b1', 'c1', 'd2', 'e2'], 
 'k31_k12_k23': ['f1', 'g1', 'h1', 'a2', 'b2', 'c2', 'd3', 'e3'], 
 'k32_k12_k22': ['f2', 'g2', 'h2', 'a2', 'b2', 'c2', 'd2', 'e2'], 
 'k31_k12_k21': ['f1', 'g1', 'h1', 'a2', 'b2', 'c2', 'd1', 'e1'], 
 'k32_k11_k23': ['f2', 'g2', 'h2', 'a1', 'b1', 'c1', 'd3', 'e3'], 
 'k32_k12_k23': ['f2', 'g2', 'h2', 'a2', 'b2', 'c2', 'd3', 'e3'], 
 'k31_k11_k21': ['f1', 'g1', 'h1', 'a1', 'b1', 'c1', 'd1', 'e1'], 
 'k31_k11_k23': ['f1', 'g1', 'h1', 'a1', 'b1', 'c1', 'd3', 'e3'], 
 'k32_k11_k21': ['f2', 'g2', 'h2', 'a1', 'b1', 'c1', 'd1', 'e1'], 
 'k32_k11_k22': ['f2', 'g2', 'h2', 'a1', 'b1', 'c1', 'd2', 'e2']}