过滤字典中的字典

5
我是Python的新手,不确定使用字典的字典是否是一个好主意,但这是我的问题。 我有一个字典的字典,我想通过内部字典的键进行过滤:
a = { 'key1' : {'id1' :[0,1,2] , 'id2' :[0,1,2], 'id3' :[4,5,6]},
     'key2' : {'id3' :[0,1,2] , 'id4' :[0,1,2]},
     'key3' : {'id3' :[0,1,2] , 'id1' :[4,5,6]}
   }

例如,我想通过'id1'进行筛选,以获得以下结果:
result = { 'key1' : {'id1' :[0,1,2] },
           'key3' : {'id1' :[4,5,6]}
         }

我已经尝试了筛选方法,但是我得到了所有的值:

r = [('key1' ,{'id1' :[0,1,2] , 'id2' :[0,1,2], 'id3' :[4,5,6]}),
     ('key3' , {'id3' :[0,1,2] , 'id1' :[4,5,6]})
   ]

此外,filter方法返回一个列表,而我想保持格式为字典。
提前感谢。

我认为你需要使用一些数据处理技术。根据你的输出规范,你可能需要使用自定义对象。 - Pwnna
4个回答

6

试试这个:

>>> { k: v['id1'] for k,v in a.items() if 'id1' in v }
{'key3': [4, 5, 6], 'key1': [0, 1, 2]}

对于 Python 2.x 版本,您可能更喜欢使用 iteritems() 而不是 items(),并且仍需要一个相当新的 Python(我认为是 2.7)才能使用字典推导式:对于较旧的 Python 版本,请使用:

dict((k, v['id1']) for k,v in a.iteritems() if 'id1' in v )

如果您想提取多个值,那么我认为最好是完整地编写循环:

def query(data, wanted):
    result = {}
    for k, v in data.items():
        v2 = { k2:v[k2] for k2 in wanted if k2 in v }
        if v2:
            result[k] = v2
    return result

提供:

>>> query(a, ('id1', 'id2'))
{'key3': {'id1': [4, 5, 6]}, 'key1': {'id2': [0, 1, 2], 'id1': [0, 1, 2]}}

这个很好用,但实际上我不想只过滤一个值,而是一个值列表(例如['id1','id2'])。 - Othman

2
根据您给Duncan的精度,这是使用字典推导筛选列表的另一种方法:
>>> my_list = ['id1', 'id2']
>>> {k1 : {k2: v2 for (k2, v2) in a[k1].iteritems() if k2 in my_list} for k1 in a}
{'key3': {'id1': [4, 5, 6]}, 'key2': {}, 'key1': {'id2': [0, 1, 2], 'id1': [0, 1, 2]}}

编辑:您还可以使用另一个字典推导式删除空值,但是那样会变得难以阅读... :-)

>>> {k3: v3 for k3, v3 in {k1 : {k2: v2 for (k2, v2) in a[k1].iteritems() if k2 in my_list} for k1 in a}.iteritems() if v3}
{'key3': {'id1': [4, 5, 6]}, 'key1': {'id2': [0, 1, 2], 'id1': [0, 1, 2]}}

遗憾的是,在中间潜伏着一个空字典。我认为此时放弃使用字典推导式,直接将所有内容全部写出来是值得的:请查看我的更新答案。 - Duncan

1
你可以使用字典推导式来完成这个任务:
def query(data, query):
    return {key : {query : data[key][query]} 
            for key in data if query in data[key]}

如果你有很多的词典条目需要查找或者频繁地进行词典查询,那么逐一检查每个词典条目将会花费很多时间。使用带有索引的数据库可以加速这个过程。


1
实际上我正在解析一个大的 CSV 文件(30 MB),那么我该如何提高速度呢? - Othman

1
field = 'id1'
dict( (k,{field: d[field]}) for k,d in a.items() if field in d)

适用于 Python 版本低于 2.7 的情况,这些版本不支持字典推导式。 - martineau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接