按值和密钥长度对字典进行排序

时间:2014-08-12 14:14:40

标签: python sorting python-3.x dictionary

我一直在谷歌搜索和搜索,我只是找不到答案。

我有一个词典,其中包含群组中的人员以及群组的分数groups = {"john,alfred,willis":5, "james,connor":5}, ...。然而,人们可以同时分成两组。我想用这本词典做的是根据人数和他们的分数来排序。例如:

>>> groups = {"a,b,c":5, "d,e":6, "f,g,h,i":5, "j,k,l":6, "m,n":10, "a,d,f":5}

我需要按分数排序,然后按人数排序,然后按字母顺序排序作为最终的打破平局。没有重复的组,但是一个组可能拥有"a,b,c,d"而另一个组可能拥有"a,b,c,e"。较高的分数胜过较低的分数,更多的人胜过较少的人,字母顺序是......字母顺序。

>>> print(mySort(groups))
"m,n", 10
"j,k,l", 6
"d,e", 6
"f,g,h,i", 5
"a,b,c", 5
"a,d,f", 5

输出格式不一定非如此,但最好是以字典的方式格式化。

我尝试了几种不同的方法,包括按,分割密钥,因为名称可以是任意长度,但因为Python不是我的第一语言,所以我&#39我觉得很难。

如何按值和字符大小对字典进行排序?

编辑:我在问题中添加了另一部分,我认为我可以不用。事实证明它需要......

3 个答案:

答案 0 :(得分:3)

使用sorted :( key函数的返回值用于比较)

>>> groups = {"a,b,c":5, "d,e":6, "f,g,h,i":5, "j,k,l":6, "m,n":10}
>>> sorted_keys = sorted(groups, key=lambda k: (groups[k], k), reverse=True)
>>> sorted_keys
['m,n', 'j,k,l', 'd,e', 'f,g,h,i', 'a,b,c']
>>> [(key, groups[key]) for key in sorted_keys]
[('m,n', 10), ('j,k,l', 6), ('d,e', 6), ('f,g,h,i', 5), ('a,b,c', 5)]

<强>更新

key功能应更改如下,以正确计算人数。

lambda k: (groups[k], len(k.split(','))), reverse=True)

答案 1 :(得分:2)

groups = {"a,b,c":5, "d,e":6, "f,g,h,i":5, "j,k,l":6, "m,n":10}
s = sorted(groups.items(),key=lambda x: (x[1],len(x[0])),reverse=True)

for k,v in s:
    print (k,v)
m,n 10
j,k,l 6
d,e 6
f,g,h,i 5
a,b,c 5

使用-max(map(ord,x[0])))按字母表中最新的字母排序,即a,b,c,y节拍a,b,c,z

In [37]: groups = {"a,b,c":5, "d,e":6, "f,g,h,i":5, "j,k,l":6, "m,n":10,"a,b,c,d":12,"a,b,c,e":12,"a,b,c,z":13,"a,b,c,y":13}

In [38]: sorted(groups.items(),key=lambda x: (x[1],len(x[0]),-max(map(ord,x[0].split(","))),reverse=True)
Out[38]: 
[('a,b,c,y', 13),
 ('a,b,c,z', 13),
 ('a,b,c,d', 12),
 ('a,b,c,e', 12),
 ('m,n', 10),
 ('j,k,l', 6),
 ('d,e', 6),
 ('f,g,h,i', 5),
 ('a,b,c', 5)]

我们使用lambda x: (x[1],len(x[0]),-max(map(ord,x[0].split(","))))对上面的输出进行排序。

x[1],len(x[0])中,我们首先对值x[1]进行排序,然后对每个键len(x[0])的长度进行排序。

如果我们与这两者相关联,我们转到-max(map(ord,x[0].split(",")),以下是一个如何运作的示例:

如果我们将"a,b,c,z" and "a,b,c,y"作为示例并将其放入列表keys =["a,b,c,z","a,b,c,y"]中:

首先获得每个char的ords:

In [54]: ords = [list(map(ord,x.split(","))) for x in keys] # get ord values from each char
In [55]: ords
Out[55]: [[97, 98, 99, 122], [97, 98, 99, 121]]

我们正在从最高到最低排序,因此我们使用reverse = True

In [56]: sorted([max(x) for x in ords], reverse=True) # puts "z" first because of reversing
Out[56]: [122, 121]

因此我们使用-max(x)来反转该输出:

In [57]: sorted([-max(x) for x in ords], reverse=True) # now "y" comes first
Out[57]: [-121, -122]
x中的{p> lambdagroups.items()中的每个子项,如下所示:

([('a,b,c', 5), ('a,b,c,d', 12), ('j,k,l', 6), ('d,e', 6), ('a,b,c,z', 13), ('m,n', 10), ('a,b,c,y', 13), ('a,b,c,e', 12), ('f,g,h,i', 5)])

因此,如果我们采用('a,b,c', 5) x[0] = "a,b,c"x[1] = 5

答案 2 :(得分:1)

按“人数”排序,你需要

>>> sorted(groups.items(), key=lambda p: (p[1], p[0].count(',')), reverse=True)

[('m,n', 10), ('j,k,l', 6), ('d,e', 6), ('f,g,h,i', 5), ('a,b,c', 5)]

作为旁注,逗号分隔的字符串不是表示事物组的最佳方式。考虑改为将你的dict元组编入索引:

>>> good_groups = {tuple(k.split(',')):v for k, v in groups.items()}

然后

>>> sorted(good_groups.items(), key=lambda p: (p[1], len(p[0])), reverse=True)

[(('m', 'n'), 10), (('j', 'k', 'l'), 6), (('d', 'e'), 6), (('f', 'g', 'h', 'i'), 5), (('a', 'b', 'c'), 5)]

如果您的组将要变异并且应该是列表而不是元组,则不能将它们用作dict键。考虑一个不同的数据结构,例如,一个dicts列表:

groups = [
   { 'members': ['foo', 'bar'], 'score': 5 },
   { 'members': ['baz', 'spam'], 'score': 15 },
etc