【问题标题】:Extracting fields of a list of dictionaries into a new dictionary using glom使用glom将字典列表的字段提取到新字典中
【发布时间】:2019-08-13 14:01:47
【问题描述】:

我有以下高度简化的结构

elements = [{"id": "1", "counts": [1, 2, 3]},
            {"id": "2", "counts": [4, 5, 6]}]

我希望能够使用glom 构造一个{<id>: <counts[pos]>} 形式的新字典,例如对于pos = 2

{"1": 3, "2": 6}

或者一个元组列表/元组

[("1",3), ("2", 6)]

使用dict comprehension 很容易,但数据结构更复杂,我想动态指定要提取的内容。前面的例子是我想要实现的最简单的事情。

过了一会儿,我设法解决了它

from glom import glom, T

elements = [{"id": "1", "counts": [1,2,3]},{"id": "2", "counts": [4,5,6]}]

def extract(elements, pos):
    extracted = glom(elements, ({"elements": [lambda v: (v["id"], v["counts"][pos])]}, T))
    return dict(extracted["elements"])

但这需要调用dict。跳过字典间接的轻微变化是

def extract(elements, pos):
    extracted = glom(elements, (([lambda v: {v["id"]: v["counts"][pos]}]), T))
    return {k: v for d in extracted for k, v in d.items()}

现在,我可以使用 merge 函数调用来自 glom 调用的返回值

def extract(elements, pos):
    return merge(glom(elements, (([lambda v: {v["id"]: v["counts"][pos]}]), T)))

我对此很满意,但有更好的方法吗?更好的意思是构建一个可调用的清洁规范?最终,我希望能够在运行时以用户友好的方式定义字典的值,即v["counts"][pos]

对这个想法的改进是使用一个可调用的对象来调用内部字典的值

def counts_position(element, **kwargs):
    return element["counts"][kwargs["pos"]]

def extract(elements, func, **kwargs):
    return merge(glom(elements, (([lambda v: {v["id"]: func(v, **kwargs)}]), T)))

extract(values, counts_position, pos=2)

这样,从每个元素中提取的内容可以在外部进行控制。

【问题讨论】:

  • FWIW,我不明白您为什么需要 glom 以及如何评估清洁度(“构建一个可调用的清洁器规范”)...
  • 这个例子很傻,但这是一个玩具例子。并不是说我需要glom,但我正在探索如何使用它来构建一些灵活的方法来从可迭代的嵌套字典中提取数据,而无需预先创建不同的函数。关于“清洁度”,我不知道如何评价,但我的解决方案感觉很麻烦。
  • 问题是我没有看到你需要那种灵活性。我猜你的意思是“我想编写一个函数extract(values, accessor, pos),其中values 始终是具有id 和不同其他键的字典列表,accessor 由用户提供(例如v["counts"][pos] ),我的代码将使用用户提供的 accessor 和不同的 pos 值调用它?
  • 如果修复了这么多,将 glom 调用“推入”字典理解可能会更清晰:{t["id"]: glom.glom(t, "counts.2") for t in elements}(否则将是glom.glom(elements, glom.Merge([{T['id']: 'counts.2'}])))。至于使用pos 参数,将其插入到'counts.%s' % pos 之类的字符串中怎么样?否则,我认为一个更现实的例子将有助于提供一个好的答案。
  • @Nickolay 看起来很棒!就我目前而言,我认为这是一个有效的答案。

标签: python glom


【解决方案1】:

要将每个带有id 的dicts 列表转换为id-keyed dict,您可以使用简单的dict理解:

{t["id"]: glom.glom(t, "counts.2") for t in elements}

或者,如果您想为此使用glom,use glom.Merge along with glom.T

glom.glom(elements, glom.Merge([{T['id']: 'counts.2'}])))

为避免使用 lambda,您可以将 pos 参数插入到规范字符串中,例如'counts.%s' % pos.

【讨论】:

    猜你喜欢
    • 2019-07-12
    • 2017-08-29
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-24
    • 2019-01-16
    相关资源
    最近更新 更多