python根据键值过滤字典列表
Posted
技术标签:
【中文标题】python根据键值过滤字典列表【英文标题】:python filter list of dictionaries based on key value 【发布时间】:2015-05-17 01:50:30 【问题描述】:我有一个字典列表,每个字典都有一个(比方说)“类型”键,其值可以是'type1'
、'type2'
等。我的目标是将这些字典过滤到一个列表中相同的词典,但只有特定“类型”的词典。我想我真的在为list/dictionary
理解而苦苦挣扎。
所以示例列表如下所示:
exampleSet = ['type':'type1','type':'type2','type':'type2', 'type':'type3']
我有一个键值列表。比如说:
keyValList = ['type2','type3']
预期的结果列表如下所示:
expectedResult = ['type':'type2','type':'type2','type':'type3']
我知道我可以使用一组 for 循环来做到这一点。我知道必须有一个更简单的方法。我发现这个问题有很多不同的风格,但没有一个真正符合要求并回答了这个问题。我会尝试发布答案……但它们并没有那么令人印象深刻。可能最好让它保持开放式。任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:你可以试试list comp
>>> exampleSet = ['type':'type1','type':'type2','type':'type2', 'type':'type3']
>>> keyValList = ['type2','type3']
>>> expectedResult = [d for d in exampleSet if d['type'] in keyValList]
>>> expectedResult
['type': 'type2', 'type': 'type2', 'type': 'type3']
另一种方法是使用filter
>>> list(filter(lambda d: d['type'] in keyValList, exampleSet))
['type': 'type2', 'type': 'type2', 'type': 'type3']
【讨论】:
哪个最快? @DarkSkull 我不确定,因为我没有测试过。随意对其进行测试并根据您的发现发布答案。 :) 如果keys
不同怎么办?不只是单身type
?【参考方案2】:
使用filter
,或者如果exampleSet
中的字典数量过多,请使用itertools
模块的ifilter
。它会返回一个迭代器,而不是一次用整个列表填满系统的内存:
from itertools import ifilter
for elem in ifilter(lambda x: x['type'] in keyValList, exampleSet):
print elem
【讨论】:
注意:对于 Python3,内置的 filter() 函数返回一个迭代器; itertools.ifilter 已被删除。【参考方案3】:尝试了这篇文章中的几个答案,我测试了每个答案的性能。
我最初的猜测是,list comprehension is way faster、filter
和 list
方法排在第二位,pandas
排在第三位。
定义变量:
import pandas as pd
exampleSet = ['type': 'type' + str(number) for number in range(0, 1_000_000)]
keyValList = ['type21', 'type950000']
第一 - list comprehension
%%timeit
expectedResult = [d for d in exampleSet if d['type'] in keyValList]
每个循环 60.7 ms ± 188 µs(平均值 ± 标准偏差,7 次运行,每次 10 个循环)
第二个 - filter
和 list
%%timeit
expectedResult = list(filter(lambda d: d['type'] in keyValList, exampleSet))
每个循环 94 毫秒 ± 328 微秒(平均值 ± 标准偏差,7 次运行,每次 10 次循环)
第三个 - pandas
%%timeit
df = pd.DataFrame(exampleSet)
expectedResult = df[df['type'].isin(keyValList)].to_dict('records')
每个循环 336 毫秒 ± 1.84 毫秒(平均值 ± 标准偏差,7 次运行,每个循环 1 个)
附带说明,使用pandas
处理dict
不是一个好主意,因为pandas.DataFrame
基本上是一个更消耗内存的dict
,如果你不是最后要使用数据框效率很低。
【讨论】:
【参考方案4】:通用方法到filter the list of dictionaries based on key-value pairs
def get_dic_filter_func(**kwargs):
"""Func to be used for map/filter function,
returned func will take dict values from kwargs keys and compare resulted dict with kwargs"""
def func(dic):
dic_to_compare = k: v for k, v in dic.items() if k in kwargs
return dic_to_compare == kwargs
return func
def filter_list_of_dicts(list_of_dicts, **kwargs):
"""Filter list of dicts with key/value pairs
in result will be added only dicts which has same key/value pairs as in kwargs """
filter_func = get_dic_filter_func(**kwargs)
return list(filter(filter_func, list_of_dicts))
测试用例 / 使用方法
def test_filter_list_of_dicts(self):
dic1 = 'a': '1', 'b': 2
dic2 = 'a': 1, 'b': 3
dic3 = 'a': 2, 'b': 3
the_list = [dic1, dic2, dic3]
self.assertEqual([], filter_list_of_dicts(the_list, x=1))
self.assertEqual([dic1], filter_list_of_dicts(the_list, a='1'))
self.assertEqual([dic2], filter_list_of_dicts(the_list, a=1))
self.assertEqual([dic2, dic3], filter_list_of_dicts(the_list, b=3))
【讨论】:
【参考方案5】:这种类型的过滤在 Pandas 中很容易实现,尤其是在很多情况下,字典列表作为 Pandas 数据框的表现更好。
import pandas as pd
exampleSet = ['type':'type1', 'type':'type2', 'type':'type2', 'type':'type3']
keyValList = ['type2', 'type3']
df = pd.DataFrame(my_list)
df[df['type'].isin(keyValList)]
结果:
type
1 type2
2 type2
3 type3
并按照 OP 的要求以字典形式取回:
expectedResult = df[df['type'].isin(keyValList)].to_dict('records')
# the result will be ['type': 'type2', 'type': 'type2', 'type': 'type3']
【讨论】:
以上是关于python根据键值过滤字典列表的主要内容,如果未能解决你的问题,请参考以下文章
Python列表元素为字典时,如何根据其中某个相同的键值进行元素合并