Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 嵌套词典中的移位词典_Python_Dictionary - Fatal编程技术网

Python 嵌套词典中的移位词典

Python 嵌套词典中的移位词典,python,dictionary,Python,Dictionary,我有下面的嵌套字典和列表列表。我想创建一个新的父类(L0)类别,名为'food',并将水果和vegs字典中的所有值向下移动一步(以便'L0':'fruit'变成'L1':'fruit','L1':'banana变成'L2':'banana,等等) 例外输出应如下所示: Expected_output = [ { "L0": "food", "L1_list": [ { "L1": "fruit",

我有下面的嵌套字典和列表列表。我想创建一个新的父类(
L0
)类别,名为
'food'
,并将
水果
vegs
字典中的所有值向下移动一步(以便
'L0':'fruit'
变成
'L1':'fruit'
'L1':'banana
变成
'L2':'banana
,等等)

例外输出应如下所示:

Expected_output = [
    {
        "L0": "food",
        "L1_list": [
            {
                "L1": "fruit",
                "L2_list": [
                    {
                        "L2": "banana"
                    },
                    {
                        "L2": "apple",
                        "L3_list": [
                            {
                                "L3": "Green apple"
                            },
                            {
                                "L3": "Redapple"
                            }
                        ]
                    },
                    {
                        "L2": "kiwi"
                    }
                ]
            },
            {
                "L1": "vegs",
                "L2_list": [
                    {
                        "L2": "potato"
                    },
                    {
                        "L2": "carrot"
                    }
                ]
            }
        ]
    }
]
现在,因为我的字典在大小和深度上可能有所不同,所以我需要一个编程解决方案。所以我想我应该创建一个递归函数,在它到达树的末尾时进行迭代。当函数到达特定分支的末尾时,它将向键添加1(
L0
-->
L1
L1\u list
-->
L2\u list
)。虽然这个过程确实将所有内容向下移动了一层,但我不知道如何重建初始结构。特别是,我不能把孩子们带回他们各自的名单

Final_list = []
def digger(list_to_dig):
    import re
    for x in list_to_dig:
        for k,v in x.items():
            if isinstance(v, list):
                print("keep digging")
                digger(v)
            elif isinstance(x, dict):
                new_D = {}
                new_k = "L" + str(int(re.sub("L", "", k)) + 1)
                new_D[new_k] = v
                temp = re.sub("L", "", k)
                new_child_list = "L" + str(int(re.sub("_list", "", temp)) + 2) + "_list"
                new_D[new_child_list] = ""
                Final_list.append(new_D)
            else:
                print("no dictionary avail")
                pass
    print("_________")
    print(Final_list)
    print("_________")

    test = digger(D)
对我应该如何解决这个问题有什么建议吗?非常感谢

根据@running.t的建议,我尝试使用
dict.pop
方法。但是,因为它发生在一次迭代中,它会弹出旧的键,创建并插入新的键,但在下一次迭代中,它会获取刚刚创建的新键,弹出它,创建并插入一个新键,依此类推(尽管它也不会进入无限循环)

下面是一个简化的示例来说明问题:

步骤1创建新的顶级dict 步骤2:将老树添加到新列表中 步骤3将1添加到老树的所有键
您不应该创建新列表并将所有内容放入其中。实际上,这就是你在排队时所做的:

Final_list.append(new_D)
相反,您应该做的是递归地迭代您拥有的所有字典和列表(与当前的方法相同),如果对象是dict,则相应地重命名该dict中的所有键

。我认为建议使用以下方法:

new_k = "L"+str(int(re.sub("L","",k))+1) 
x[new_key] = x.pop(k)

最后,在完成所有
D
挖掘后,您应该将修改后的
D
放入新的
预期输出列表中。

我知道,晚了一年,但让我们用散文快速分析一下问题。你有一本字典。字典可以有两种类型的键:
L*
L*\u list
。在这两种情况下,
*
都是整数<代码>L*
将始终具有字符串值<代码>L*_列表
将始终有一个字典值列表。您的目标是递归递增键名称中的整数

很明显,类似的东西很适合递归。您递归到
L*\u列表的每个元素中。当您得到一个没有
L*\u list
键的字典列表时,递归结束。在这种情况下,只需增加
L*
键并返回。到目前为止,我们完全同意,因为我所说的一切都已经在讨论中

为了回答实际问题,我们只需要做一个更改:递归函数需要修改嵌套对象,或者返回一个新的替换对象。构造一个全新的数据结构比修改现有的字典更简单,因为它使迭代更容易(您也注意到了这一点)

在顶层有一个特殊的情况,因为你想把所有的东西都放到一个新的
食品
类别中。这不是问题,因为递归解决方案将返回新的
L1\u列表
键的值

下面是一个简单的示例实现:

def increment_keys(d):
    def process_key(key, value):
        key = f'L{int(key[1:]) + 1}'
        return key, value

    def process_list(key, value):
        key = f'L{int(key[1:-5]) + 1}_list'
        value = [increment_keys(d) for d in value]
        return key, value

    def process(key, value):
        if key.endswith('_list'):
            return process_list(key, value)
        return process_key(key, value)

    return dict(process(key, value) for key, value in d.items())

expected_output = [{'L0': 'food', **increment_keys({'L0_list': D})}]
您可以将嵌套的
进程
函数吸收到生成器中,该生成器通过使用三元运算符输入
递增键
的返回值。我认为它不会提高可读性,但会为您节省大约四行:

return dict(process_list(k, v) if k.endswith('_list') else process_key(k, v) for k, v in d)
现在,如果必须在适当的位置执行此操作,最好的方法是在迭代之前冻结每个字典的键。如果对冻结的键进行迭代,
pop
\uuuuu setitem\uuuu
将不会给您带来任何问题

由于在给定的级别上,原始键和递增键之间永远不会出现重复,因此不必特别注意丢失先前的值(例如,如果在同一个dict中有
L1
L2
,并且先递增
L1

下面是一个就地递归示例:

def increment_keys(obj):
    def process(d):
        for key in list(d.keys()):
            value = d.pop(key)
            if key.endswith('_list'):
                key = f'L{int(key[1:-5]) + 1}_list'
                increment_keys(value)
            else:
                key = f'L{int(key[1:]) + 1}'
            d[key] = value

    for d in obj:
        process(d)

increment_keys(D)
expected_output = [{'L0': 'food', 'L1_list': D}]

按照Python惯例,我没有从就地函数返回任何内容。

你从哪里获得初始字典?你自己构建的吗?是的,我手动构建了特定的字典。不过在最终解决方案中,它将由最终用户通过UI构建。
L10
?谢谢!非常有用。我不是familiar将使用pop函数,但会研究它并让您知道它是如何运行的
new_k = "L"+str(int(re.sub("L","",k))+1) 
x[new_key] = x.pop(k)
def increment_keys(d):
    def process_key(key, value):
        key = f'L{int(key[1:]) + 1}'
        return key, value

    def process_list(key, value):
        key = f'L{int(key[1:-5]) + 1}_list'
        value = [increment_keys(d) for d in value]
        return key, value

    def process(key, value):
        if key.endswith('_list'):
            return process_list(key, value)
        return process_key(key, value)

    return dict(process(key, value) for key, value in d.items())

expected_output = [{'L0': 'food', **increment_keys({'L0_list': D})}]
return dict(process_list(k, v) if k.endswith('_list') else process_key(k, v) for k, v in d)
def increment_keys(obj):
    def process(d):
        for key in list(d.keys()):
            value = d.pop(key)
            if key.endswith('_list'):
                key = f'L{int(key[1:-5]) + 1}_list'
                increment_keys(value)
            else:
                key = f'L{int(key[1:]) + 1}'
            d[key] = value

    for d in obj:
        process(d)

increment_keys(D)
expected_output = [{'L0': 'food', 'L1_list': D}]