gpt4 book ai didi

python - 按多个值过滤字典

转载 作者:太空狗 更新时间:2023-10-30 02:18:16 24 4
gpt4 key购买 nike

我是 Python 的新手,我很难制定一种“pythony”过滤字典的方法。

我有一本看起来像这样的字典:

'217': {'586': 2.0, '578': 5.0, '172': 1.0, '1222': 1.0, '597': 4.0, '1303': 2.0, '195': 5.0, ...}
'660': {'176': 4.0, '174': 3.0, '231': 5.0, '233': 4.0, '797': 4.0, '541': 3.0, '27': 1.0, '210': 4.0, ...}

等等。

然后我有一个字符串列表:

['2', '4', '17', '21', '22', '24', '27', '28', '29', '33', '39', ...]

我想要实现的是一个过滤字典,其中只存在字符串列表中具有任何值的元组。我已经做到了这一点,但只使用一个字符串作为要求,它看起来像这样:

filtered_dict = {k: v for (k, v) in my_dict.iteritems() if my_list[0] in v}

但是,如果我删除 [0],则会出现以下错误:

类型错误:无法散列的类型:“列表”以下是一些预期的输出值:

'115 : {'174': 4.0, '172': 4.0, '27': 3.0, '183': 5.0, '180': 3.0, '1039': 5.0, ... }

'212' : {'4': 3.0, '473': 4.0, '208': 5.0, '123': 4.0, '476': 3.0, '474': 4.0, ...}

如您所见,第一个元组中的第三个值在 my_list 中有“27”。第二个元组中的第一个值的值为“4”,它也在 my_list 中。

我将非常感谢任何形式的帮助。

谢谢!

最佳答案

您可以使用集合,如果值与集合不相交则保持成对:

st = {'2', '4', '17', '21', '22', '24', '27', '28', '29', '33', '39'}

filtered_dict = {k: v for (k, v) in my_dict.iteritems() if not st.isdisjoint(v)}

只有当它们不共享至少一个元素时,它们才会不相交:

In [6]: st ={1,2,3}

In [7]: v = [1,4,5]

In [8]: st.isdisjoint(v)
Out[8]: False

In [11]: v = [7,4,5]

In [12]: st.isdisjoint(v)
Out[12]: True

它有点等同于:

st = {'2', '4', '17', '21', '22', '24', '27', '28', '29', '33', '39'}

filtered_dict = {k: v for (k, v) in my_dict.iteritems() if any(val in st for val in v)}

如果 any来自 v 的元素在我们保留元素的集合中。

最坏的情况是我们检查 len(v) 元素与集合,遍历 mylist 元素并检查 x 是否在 v 中是 O(len( my_list)) 每次匹配时都会创建相同的 k,v 对。

如果我们添加一个带有更多匹配键的字典,并将这些对添加到列表中,您可以看到会发生什么:

In [22]: my_list  = ['2', '4', '17', '21', '22', '24', '27', '28', '29', '33', '39']

In [23]: my_dict = {'217': {'586': 2.0, '578': 5.0, '172': 1.0, '1222': 1.0, '597': 4.0, '1303': 2.0, '195': 5.0},
....: '660': {'176': 4.0, '174': 3.0, '231': 5.0, '233': 4.0, '797': 4.0, '541': 3.0, '27': 1.0, '210': 4.0},
....: '661': {'2': 4.0, '4': 3.0, '29': 5.0, '17': 4.0, '39': 4.0, '541': 3.0, '27': 1.0, '210': 4.0}}


In [24]: print [(k,v) for k,v in my_dict.iteritems() for x in my_list if x in v]
[('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('661', {'541': 3.0, '39': 4.0, '2': 4.0, '4': 3.0, '17': 4.0, '210': 4.0, '27': 1.0, '29': 5.0}), ('660', {'797': 4.0, '27': 1.0, '541': 3.0, '210': 4.0, '176': 4.0, '174': 3.0, '231': 5.0, '233': 4.0})]

因为有 7 场比赛,我们得到了七次相同的配对,你不会在字典中得到欺骗,但你将不得不迭代 len(my_list) 次并在 v< 中创建 x 的配对长度 是真实时间。随着 my_list 的长度增加,运行时间也会相应增加。

仅仅使 my_list 有 1000 个元素就有相当大的区别:

In [35]: len(my_list)
Out[35]: 1000

In [36]: %%timeit
....: st = set(my_list)
....: {k: v for (k, v) in my_dict.iteritems() if not st.isdisjoint(v)}
....:
10000 loops, best of 3: 21.9 µs per loop
In [37]: timeit {k:v for k,v in my_dict.iteritems() for x in my_list if x in v}
10000 loops, best of 3: 136 µs per loop

几乎所有时间都花在了集合创建上,如果您从一开始就使用集合,它的运行速度会快 100 倍:

In [40]: timeit {k: v for (k, v) in my_dict.iteritems() if not st.isdisjoint(v)}

1000000 loops, best of 3: 1.09 µs per loop

关于python - 按多个值过滤字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36427842/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com