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、filterlist 方法排在第二位,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 个循环)

第二个 - filterlist

%%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列表元素为字典时,如何根据其中某个相同的键值进行元素合并

根据另一个(部分)字典过滤字典列表

如何使用 python 或 pandas 根据包含字典列表的列过滤 DataFrame?

python字典列表过滤器

python字典列表过滤器

将列表转换为字典,然后通过键值将多个字典合并为一个字典