我有一个 struct 相当复杂的Python字典——多层嵌套值,其中一些是dict,一些是list.我想用一种简洁的方式来表示数据的变化,这样可以很容易地apply.

对于仅使用字典的值,这似乎不太难——您可以制作一个dict,反映主数据的 struct ,但只包括其父数据上修改过的键,并调用一个稍微修改过的.update(),在需要完全删除密钥时检测墓碑值.

但由于涉及 list ,它似乎变得更加棘手.似乎我需要想出某种定制的寻址方案,需要考虑很多情况——你不能简单地使用列表索引作为键,因为你需要支持,例如,在元素2和3之间插入的同时删除元素5.

此外,如果列表不局限于叶子,那么在修改列表元素的同时指定对列表中包含的项目的更改是很棘手的.

有没有一个Python库可以标准化这样的东西?还是一种相对合理的标准算法/方法?

作为参考,下面是一个函数,它实现了我所寻找的dict纯数据:

def update(d, u):
    for k, v in u.items():
        if v == 'del':
            del d[k]
        elif isinstance(v, collections.abc.Mapping):
            d[k] = update(d.get(k, {}), v)
        else:
            d[k] = v
    return d

>>> d = {1: 2, 3: {4: 5, 6: 7}}
>>> delta = {3: {4: 'del', 6: 8}, 9: 10}
>>> update(d, delta)
{1: 2, 3: {6: 8}, 9: 10}

推荐答案

从用户的Angular 来看,我认为列表索引并不像你说的那么重要.只有在所有操作完成后,索引才会发生变化.在列表操作期间使用旧索引.

从实现的Angular 来看,我们在操作列表索引时必须格外小心.我们可以做的是在迭代过程中保持"索引增量i",而不是修改l[k],而是修改l[k+i].

在这里,我将使用delta字典,以列表索引为键,以及以下三个可能的值:

  • 'del'删除此索引中的项目;
  • ('insert', v),在该索引前插入值v;和
  • v将此索引的值修改为v.

请注意,'del'v是互斥的,但'insert'可以是累积的:可以在同一索引中插入多个元素,也可以在索引and删除或修改该索引中的元素之前插入元素.Se我们希望dict delta能够将一个密钥映射到多个更新;i、 例如,将一个键映射到一个列表.

from operator import itemgetter

def update(d, u):
    if isinstance(d, dict):
        return update_dict(d, u)
    elif isinstance(d, list):
        return update_list(d, u)

def update_dict(d, u):
    for k, v in u.items():
        if v == 'del':
            del d[k]
        elif isinstance(v, dict):
            d[k] = update(d.get(k, {}), v)
        else:
            d[k] = v
    return d

def update_list(d, u):
    i = 0
    for k, v in sorted(u.items(), key=itemgetter(0)):
        if isinstance(v, list):
            for x in v:
                i = update_list_once(d, i, k, x)
        else:
            i = update_list_once(d, i, k, v)
    return d

def update_list_once(d, i, k, v):
    if v == 'del':
        del d[k+i]
        i -= 1
    elif isinstance(v, tuple) and len(v) == 2 and v[0] == 'insert':
        d.insert(k+i, v[1])
        i += 1
    else:
        if isinstance(v, dict):
            d[k + i] = update(d[k+i], v)
        else:
            d[k+i] = v
    return i

测试:

d = {1: 2, 3: {4: [0, 1, 2, 3, 4, 5], 6: 7}}
delta = {3: {4: {0: 'fizzbuzz', 3: 'fizz', 4: [('insert', 3.5), 4.001], 5: 'buzz'}, 6: 8}, 9: 10}
d = update(d, delta)
print(d)
# {1: 2, 3: {4: ['fizzbuzz', 1, 2, 'fizz', 3.5, 4.001, 'buzz'], 6: 8}, 9: 10}

Python相关问答推荐

追溯(最近最后一次调用):文件C:\Users\Diplom/PycharmProject\Yolo01\Roboflow-4.py,第4行,在模块导入roboflow中

发生异常:TclMessage命令名称无效.!listbox"

Julia CSV for Python中的等效性Pandas index_col参数

如何从.cgi网站刮一张表到rame?

从嵌套的yaml创建一个嵌套字符串,后面跟着点

Polars map_使用多处理对UDF进行批处理

用fft计算指数复和代替求和来模拟衍射?

高效生成累积式三角矩阵

如何写一个polars birame到DuckDB

如何在Python中从html页面中提取html链接?

文本溢出了Kivy的视区

Matplotlib中的曲线箭头样式

递归链表反转与打印语句挂起

为什么按下按钮后屏幕的 colored颜色 保持不变?

在聚合中使用python-polars时如何计算模式

#将多条一维曲线计算成其二维数组(图像)表示

使用元组扩展字典的产品挑战

极地数据帧:ROLING_SUM向前看

保存由PYTHON在EXCEL中所做更改的问题

突出显示两幅图像之间的变化或差异区域