猿问

在具有匹配属性的 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' 值的项目,并且如果有多个具有相同最低值的 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。


大话西游666
浏览 143回答 2
2回答

POPMUISE

您可以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 tagsct = {t: tags.count(t) for t in set(tags)}           # make a dict of tag:count for each unique tagmax_tag = max(ct, key=lambda x: ct[x])               # find the largest count and get the largest tagr = [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"所以基本上与上面相同的过程,但更短,效率更低,并且更复杂一些。

BIG阳

按“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]
随时随地看视频慕课网APP

相关分类

Python
我要回答