python - 在具有匹配属性的 dict 数组中查找最小值,返回最大的分组
问题描述
这很容易通过几个循环来做到这一点,但我确信有一种更有效的方法可以实现这一点,我很想学习。
考虑以下 dict 数组,它表示从 nosql 数据库中提取的数据。
x = [
{
"loc" : "alpha",
"tag" : 1,
"dist" : 5
},
{
"loc" : "bravo",
"tag" : 0,
"dist" : 2
},
{
"loc" : "charlie",
"tag" : 5,
"dist" : 50
},
{
"loc" : "delta",
"tag" : 4,
"dist" : 2
},
{
"loc" : "echo",
"tag" : 2,
"dist" : 30
},
{
"loc" : "foxtrot",
"tag" : 4,
"dist" : 2
},
{
"loc" : "gamma",
"tag" : 4,
"dist" : 2
},
{
"loc" : "hotel",
"tag" : 0,
"dist" : 2
},
]
我想找到所有具有最低“dist”值的项目,并且如果有多个具有相同最低值的字典,我希望对具有相同最小值的最多字典的属性“标签”进行分组.
例如,从上面返回的所需数据将是:
r = [
{
"LocationName" : "delta",
"tag" : 4,
"dist" : 2
},
{
"loc" : "foxtrot",
"tag" : 4,
"dist" : 2
},
{
"loc" : "gamma",
"tag" : 4,
"dist" : 2
}
]
总结:dist:2是最小值,[bravo, delta, foxtrot, gamma, hotel]的dist都是2,[bravo, hotel]的tag是:0,[delta, foxtrot, gamma]有tag的:4 。返回一个 dicts [delta, foxtrot, gamma] 的数组,因为它们有更多具有相同匹配标签和最低 dist 的数组。
我正在使用python 3.6。
感谢您的帮助和兴趣!
解决方案
您可以为and指定一个key
(即 lambda 函数)来帮助解决这个问题。对于您的第一次测试,max()
min()
lowest_single_dist = min(x, key=lambda i: i["dist"])
x
返回 中具有最低值的元素"dist"
。如果您想要所有具有该标记值的元素,则可以使用列表推导:
lowest_dists = [i for i in x if i["dist"] == lowest_single_dist["dist"]]
为了获得最大的分组,我将首先在该子集中创建一组可能的值"tag"
,然后检查每个中有多少lowest_dists
,然后取具有最高计数的那个:
tags = [i["tag"] for i in lowest_dists] # get a list of just the tags
ct = {t: tags.count(t) for t in set(tags)} # make a dict of tag:count for each unique tag
max_tag = max(ct, key=lambda x: ct[x]) # find the largest count and get the largest tag
r = [i for i in lowest_dists if i["tag"] == max_tag] # use another list comprehension to get all the max tags
如果您想将其全部缩短为两条线,则可以不那么 Pythonic 并执行以下操作:
m = min(x, key=lambda i: (i["dist"], -1 * max([j["tag"] for j in x if j["dist"] == i["dist"]].count(i["tag"])))
r = [i for i in x if i["tag"] == m["tag"] and i["dist"] == m["dist"]]
这利用了您可以返回一个元组作为排序键的事实,并且只有第一个相等时才会检查元组的第二个值。我将扩展第一行并解释每个部分在做什么:
m = min(x, key=lambda i: (
i["dist"], -1 * max(
[j["tag"] for j in x if j["dist"] == i["dist"]].count(i["tag"])
))
- 最里面的列表推导为所有元素生成一个标签列表,
x
其中的值与"dist"
as相同i
- 然后,计算与
i
- 乘以 -1 使其为负数,以便
min()
正确运行 - 制作一个元组
i["dist"]
和我们刚刚计算的值(i["tag"]
in的频率x
),并为每个元素返回它 - 分配给
m
列表中具有最低值"dist"
和最频繁值的元素"tag"
- 分配给具有相同值的
r
元素的子列表x
"dist"
"tag"
所以基本上与上面的过程相同,但更短,效率更低,而且更复杂一些。
推荐阅读
- swift - 有没有办法在 UIPickerView 上从 Firebase 实时数据库打印数据?
- cidr - CIDR 和 IP 地址数
- c# - 如何建立匿名参数数组
- excel - 无法使用 vba 在散点图上绘制值
- ios - 如何强制 iOS 12 的主屏幕 Web 应用程序自动更新?
- javascript - 当焦点在输入字段中时,为什么日期选择器在 React 中闪烁?
- vba - 更换 PowerPoint 演示文稿中的字体时遇到问题
- c - 为什么函数指针不命名它们的参数?
- widget - 例如,如何在 odoo12 中创建一个下拉列表并用 1 到 5 的值填充它
- python - 只允许两个人使用不和谐的机器人命令