【问题标题】:There must be a more optimal way to parse two files解析两个文件一定有更优化的方式
【发布时间】:2014-11-07 00:08:24
【问题描述】:

我目前正在使用 Python 2.7 解析两个 JSON 文件。目标是检查 file1 中的每个 JSON 对象与 file2 上的每个 JSON 对象,并使用它们的“名称”键进行比较。如果匹配,则用 obj1 数据覆盖 obj2。我现在的伪代码(如下)将在 O(n^4) 时间内运行。这太慢了,所以如果有人能指出一个更快的方法,我将不胜感激。

for obj1 in file1:
   for key1, value1 in obj1.iteritems():
       if key1 == 'name':
           for obj2 in file2:
               for key2, value2 in obj2.iteritems():
                   if key2 == 'name':
                       if value1 == value2:
                           overwrite obj2 using obj1 data

【问题讨论】:

  • 你的意思是覆盖值还是添加值?
  • 覆盖,编辑
  • 为什么不直接使用obj1["name"]等..
  • 请注意,如果您所寻找的只是一键,则无需遍历obj1obj2。只需执行obj1['name']obj2['name'] 并忽略其他键。

标签: python json parsing python-2.7


【解决方案1】:

您的文件有多大?将它们加载到内存中是否有任何问题?我会做类似以下伪代码的事情:

我假设 obj1, obj2 是字典,因为您使用的是 iteritems。

dict1 = dict( (o['name'], o) for o in file1 )
dict2 = dict( (o['name'], o) for o in file2 )
dict2.update(dict1)

【讨论】:

  • 您更新数据不正确。 dict1 数据应该覆盖 dict2 数据,而不是相反,您可能不应该替换嵌套字典。
  • 你的代码也有错别字;第二行的括号不平衡。而且你不需要先建立一个列表;删除两行中的[...] 会使代码更高效。
  • 修正错字。并感谢您指出 [...]。我不知道您可以直接使用 dict() 进行列表理解。
  • 称为生成器表达式。请注意,您现在完全替换了 dict2 中的项目;如果dict2 中的任何o 对象比dict1 中的相应对象拥有更多 个键,那么这些键现在将丢失。
【解决方案2】:

将来自file1 的对象存储在字典中,以name 为键:

file1_names = {}
for obj1 in file1:
    if 'name' not in obj1:
        continue
    file1_names.setdefault(obj1['name'], []).append(obj1)

现在您可以在 O(1) 时间内查找这些对象:

for obj2 in file2:
    if 'name' not in obj2:
        continue
    for obj1 in file1_names.get(obj2['name'], []):
        obj2.update(obj1)

以上代码仅扫描file1file2 一次,使得整体时间复杂度 O(N),其中 N 是两个文件中对象的总数。

我做了以下假设:

  • obj1 中的名称不是唯一的,因此按名称将它们收集到列表中。
  • 'name' 键可能丢失。

如果这些假设不成立(因此名称是唯一的并且总是给定的),您可以将上述简化为:

file1_names = {o['name']: o for o in file1}
for obj2 in file2:
    obj2.update(file1_names.get(obj2['name'], {}))

【讨论】:

猜你喜欢
  • 2020-06-19
  • 1970-01-01
  • 2014-06-26
  • 1970-01-01
  • 2018-05-31
  • 1970-01-01
  • 2020-03-15
  • 1970-01-01
  • 2010-09-18
相关资源
最近更新 更多