为了账号安全,请及时绑定邮箱和手机立即绑定

在具有匹配属性的 dict 数组中查找最小值,返回最大的分组

在具有匹配属性的 dict 数组中查找最小值,返回最大的分组

大话西游666 2021-08-14 16:43:03
这很容易通过几个循环来做到这一点,但我相信有一种更有效的方法来实现这一点,我很想学习。考虑以下 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' 值的项目,并且如果有多个具有相同最低值的 dict,我希望对具有相同最低值的 dict 最多的属性 'tag' 进行分组.例如,上面所需的返回数据是: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] 的标签是:0,[delta, foxtrot, gamma] 的标签都是的:4。返回一个 dicts [delta, foxtrot, gamma] 数组,因为它们有更多具有相同匹配标签和最低 dist 的。我正在使用 python 3.6。
查看完整描述

2 回答

?
POPMUISE

TA贡献1765条经验 获得超5个赞

您可以key为max()和指定一个(即 lambda 函数),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"asi

  • 然后,取与相同的标签计数 i

  • 乘以 -1 使其为负数,以便min()正确运行

  • 创建一个i["dist"]和我们刚刚计算的值(i["tag"]in的频率x)的元组,并为每个元素返回该值

  • 分配给m列表中具有最低值"dist"和最频繁值的元素"tag"

  • 分配给具有相同值r的元素的子列表和x"dist""tag"

所以基本上与上面相同的过程,但更短,效率更低,并且更复杂一些。


查看完整回答
反对 回复 2021-08-14
?
BIG阳

TA贡献1859条经验 获得超6个赞

按“dist”中的值对字典列表进行排序,并取最低值


x.sort(key= lambda x:x['dist'])

lowest = x[0]['dist']

创建一个字典列表,其中 'dist' 的值等于最低值


x2 = [i for i in x if i['dist']==lowest]

这应该是你的答案。如果列表中有多个项目,请重复上述过程。


if len(x2)>1:

  x3 = [i['tag'] for i in x2]

  mode = max(set(x3), key=x3.count)

  r = [i for i in x if i['tag']==mode]


查看完整回答
反对 回复 2021-08-14
  • 2 回答
  • 0 关注
  • 142 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号