用元组键展平嵌套字典 [英] Flatten nested dictionaries with tuple keys

查看:56
本文介绍了用元组键展平嵌套字典的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将此问题归纳为可能是元组的案例关键字?

How to generalize this question to the case keys that may be tuples?

即使在所有字符串键的情况下,这也是一个好处,如果将它们累积到一个元组,则不需要临时分隔符(尽管JSON导出是另一回事):

As a benefit even in the case of all string keys, if these are accumulated to a tuple, there's no need for ad-hoc separators (though JSON export is another matter):

一种方法是基于此答案.我尝试了2个版本:

one approach is to base it on this answer. I tried 2 versions:

def flatten_keys(d,handler,prefix=[]):
    return {handler(prefix,k) if prefix else k : v
        for kk, vv in d.items()
        for k, v in flatten_keys(vv, handler, kk).items()
        } if isinstance(d, dict) else { prefix : d }

元组处理程序在哪里:

def tuple_handler_1(prefix,k):
    return tuple([prefix]+[k])

def tuple_handler_2(prefix,k):
    return tuple(flatten_container((prefix,k)))

使用实用程序生成器:

def flatten_container(container):
    for i in container:
        if isinstance(i, (list,tuple)):
            for j in flatten_container(i):
                yield j
        else:
            yield i

考虑其中一个测试字典,但使用元组键('hgf',1):

Consider one of the test dict's but using a tuple key ('hgf',1):

data =  {'abc':123, ('hgf',1):{'gh':432, 'yu':433}, 'gfd':902, 'xzxzxz':{"432":{'0b0b0b':231}, "43234":1321}}

均未达到预期的效果:

flatten_keys(data,tuple_handler_1)

{'abc':123,((('hgf',1),'gh'):432,((''hgf',1),'yu'):433,'gfd':902,('xzxzxz',('432','0b0b0b')):231,('xzxzxz','43234'):1321}

{'abc': 123, (('hgf', 1), 'gh'): 432, (('hgf', 1), 'yu'): 433, 'gfd': 902, ('xzxzxz', ('432', '0b0b0b')): 231, ('xzxzxz', '43234'): 1321}

('xzxzxz',('432','0b0b0b')).没有展平

第二个将输入的元组键变平

And the 2nd flattens the input tuple key

flatten_keys(data,tuple_handler_2)

{'abc':123,('hgf',1,'gh'):432,('hgf',1,'yu'):433,'gfd':902,('xzxzxz','432','0b0b0b'):231,('xzxzxz','43234'):1321}

{'abc': 123, ('hgf', 1, 'gh'): 432, ('hgf', 1, 'yu'): 433, 'gfd': 902, ('xzxzxz', '432', '0b0b0b'): 231, ('xzxzxz', '43234'): 1321}

扁平化方法是否有明显的修改,可以正确连接字符串和其他哈希值?

Is there an obvious modification of the flatten method that will correctly join strings and other hashables?

编辑

根据下面的评论,使用此方法处理键冲突是字符串键的基本情况,例如 {'a_b':{'c':1},'a':{'b_c':2}} .

As per comments below, a problem handling key-clash with this method is inherent the base case of strings keys, eg {'a_b':{'c':1}, 'a':{'b_c':2}}.

因此,即使对于 len 1个键路径,每个键路径也应该是一个元组,以避免键冲突,例如 {(((1,2),):3,(1,2):4}} .

Thus each key path should be a be tuple even in for len 1 key paths to avoid key clash eg {((1,2),): 3, (1,2):4}}.

推荐答案

假设您需要以下输入/输出

Assuming you want the following input/output

# input
{'abc': 123,
 ('hgf', 1): {'gh': 432, 'yu': 433},
 'gfd': 902,
 'xzxzxz': {'432': {'0b0b0b': 231}, '43234': 1321}}

# output
{('abc',): 123,
 (('hgf', 1), 'gh'): 432,
 (('hgf', 1), 'yu'): 433,
 ('gfd',): 902,
 ('xzxzxz', '432', '0b0b0b'): 231,
 ('xzxzxz', '43234'): 1321}

一种方法是对字典进行递归,直到找到一个非字典值,然后在递归过程中将当前键作为元组向下传递.

One approach is to recurse on your dictionary until you find a non-dictionary value and pass down the current key as a tuple during the recursion.

def flatten_dict(deep_dict): 
    def do_flatten(deep_dict, current_key): 
        for key, value in deep_dict.items():
            # the key will be a flattened tuple
            # but the type of `key` is not touched
            new_key = current_key + (key,)
            # if we have a dict, we recurse
            if isinstance(value, dict): 
                yield from do_flatten(value, new_key) 
            else:
                yield (new_key, value) 
    return dict(do_flatten(deep_dict, ()))

这篇关于用元组键展平嵌套字典的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆