【问题标题】:Python efficient way to filter dictPython过滤dict的有效方法
【发布时间】:2017-09-29 09:18:03
【问题描述】:

我有一个非常简单(但非常大)的 JSON 文件,我需要对其进行一些过滤。 (我已经有一段时间没有做任何python了......)

看起来像这样:

{
    'entry_1': {
        'field_1' : 'value',
        'field_2' : 123,
        'field_3' : '',
        'field_4' : 456
    },
    'entry_2': {
        'field_1' : 'value',
        'field_2' : 321,
        'field_3' : 'value',
        'field_4' : 654
    },
    ...
}

我想过滤它以删除无用的字段。我的测试文件很小,我做的很好,但我需要在一个相当大的文件上做,而且我知道我的代码很丑。

到目前为止,我已经这样做了:

dict_in = json.load(INFILE)
dict_out = defaultdict(dict) #4harambe

allowed_fields = {'field_1', 'field_3'} 
'''should I use a set or a tuple here ? or maybe something else
All data inside will be unique (set) but 
those data wont change (tuple)
'''

for entry in dict_in:
    for field in dict_in[entry]:
        if field in allowed_fields and not dict_in[entry][field]:
            # allowed field plus non empty string
            dict_out[entry][field] = dict_in[entry][field]

我想知道如何让它更性感、更高效(双循环 + if 语句以及我访问数据的方式非常糟糕)。我已经阅读过 itertools,但我还不知道如何使用它以及它是否是个好主意。

【问题讨论】:

  • 将其保留为 set() O(1) 与元组 O(n)。此外,从下面的答案来看,你的答案是最易读的,并且性能可能完全相同。

标签: python json performance dictionary filtering


【解决方案1】:

只是:

dict_out = {k: {f: v[f] for f in allowed_fields if v.get(f)} 
            for k, v in dict_in.items()}

注意:

如果您仍在使用 python 2.7,请使用 .iteritems() 而不是 .items()

【讨论】:

  • 好答案。一个警告:对于 Python 2.7,最好使用 .iteritems() 代替,因为 .items() 将所有项目分开 list — 这对于大型对象来说效率很低。在 Python 3.x 中这是不必要的。
  • @DanLenski 我已经添加了这一点,作为仍然在 2.7 的压迫性枷锁下受苦的同胞的说明
  • @donkopotamus...不能和你争论。是时候回到古老专有数据库模块矿山的辛劳了。
  • @donkopotamus 没有得到那个部分!我会删除我的评论。
  • @DanLenski 需要更多的幽默感,谢谢
【解决方案2】:

您可以使用dictionary comprehensions 编写它:

allowed_fields = {'field_1', 'field_3'}
dict_out = {
    entry_key: {
        field: field_value
        for field, field_value in entry_value.items()
        if field in allowed_fields and field_value
    }
    for entry_key, entry_value in dict_in.items()
}

它为所有 field_1field_3 键提供非空值:

{'entry_1': {'field_1': 'value'},
 'entry_2': {'field_1': 'value', 'field_3': 'value'}}

【讨论】:

    【解决方案3】:

    无需遍历内部dicts,直接获取值即可:

    def grabber(d, fields, default=None):
        return dict((f, d.get(f, default)) for f in fields) 
    
    dict_out = {k:grabber(v, allowed_fields) for k,v in dict_in.items()} 
    

    【讨论】:

      【解决方案4】:

      给定 dict_in 作为输入和您需要的 fields

      fields = ['field_1', 'field_4']
      dict_out = dict([(k, {_k: _v for _k, _v in v.items() if _k in fields}) for k, v in dict_in.items()])
      

      dict_out 将如下所示:

      {'entry_1': {'field_1': 'value', 'field_4': 456},
       'entry_2': {'field_1': 'value', 'field_4': 654}}
      

      【讨论】:

        猜你喜欢
        • 2013-01-19
        • 2021-11-24
        • 2010-12-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多