更快的方式在python中进行通信替换操作?

时间:2013-05-10 14:13:04

标签: python performance algorithm dictionary merge

我不确定我是否正在使用正确的术语---我可以称之为合并操作吗?简单匹配?

我有两本词典。其中一个包含标签ID列表。另一个是标签ID和标签ID名称之间的对应关系。我想匹配ID并在第一个字典中包含标记名称。

所以,第一个字典看起来像这样:

>>> myjson
[
{"tags" : ["1","3"],"otherdata" : "blah"},
{"tags" : ["2","4"],"otherdata" : "blah blah"}
]

第二个字典看起来像这样:

>>> tagnames
[
{"id": "1", "name":"bassoon"},
{"id": "2", "name":"banjo"},
{"id": "3", "name":"paw paw"},
{"id": "4", "name":"foxes"}
]

要使用标记ID名称替换myjson中的标记ID,我目前正在执行此操作:

data = []
for j in myjson:
    d = j
    d['tagnames'] = [i['name'] for i in tagnames for y in d['tags'] if y==i['id']]
    data.append(d)

我想要的输出是:

>>> data
[
{"tags" : ["1","3"],"otherdata" : "blah", "tagname" : ["bassoon","paw paw"]},
{"tags" : ["2","4"],"otherdata" : "blah blah", "tagname": ["banjo","foxes"]}
]

我得到了正确的输出,但看起来真的很慢。我知道它每次都在myjson中对每个元素进行完整迭代x每个元素在标记名中的完整迭代(是mxn?nxn?),这会很慢,但也许有一个更聪明的语法或技巧来加速它?只运行一次而不是n次?

哦,如果有人可以通过光滑的地图或功能方法而不是外部的forloop建议一种方法来做这个任务,那就太酷了。

1 个答案:

答案 0 :(得分:2)

您希望将标记名列表转换为字典:

tagnames_map = {t['id']: t['name'] for t in tagnames}

现在您可以更快地找到匹配的标记名;您的代码已经进行了就地更改,因此我将其简化为:

for d in myjson:
    d['tagnames'] = [tagnames_map[t] for t in tagnames_map.viewkeys() & d['tags']]

dict.viewkeys() method返回dictionary view object,其作用类似于集合。我们将该集合与您的标记列表相交,从而生成tagnames_map中列出的一系列标记。通过这样做,我们不必担心地图中缺少任何标记。

如果您使用的是Python 3,那么您只需直接使用tagnames_map.keys();在Python 3中,.keys().values()items()方法已更改为始终返回字典视图对象。

如果您想要制作副本,请使用d.copy()

data = []
for d in myjson:
    d = d.copy()
    d['tagnames'] = [tagnames_map[t] for t in tagnames_map.viewkeys() & d['tags']]
    data.append(d)

dict.copy()创建一个浅拷贝;不会复制可变值,新的dict将只引用相同的值。因为你没有在这里改变价值观,所以很好。

针对您的示例输入运行此命令:

>>> pprint(data)
[{'otherdata': 'blah', 'tagnames': ['bassoon', 'paw paw'], 'tags': ['1', '3']},
 {'otherdata': 'blah blah',
  'tagnames': ['banjo', 'foxes'],
  'tags': ['2', '4']}]