【问题标题】:Sorting dictionary by value and key length按值和键长度对字典进行排序
【发布时间】:2014-08-12 14:14:39
【问题描述】:

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

我有一本字典,其中包含组中的人员,以及该组的分数,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 不是我的第一语言,所以我觉得很难。

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

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

【问题讨论】:

  • 可能重复:stackoverflow.com/questions/613183 本质上,您无法对字典进行排序,只需以排序方式显示即可。
  • 反对者,解释一下? @iwin,这是怎么重复的?
  • @iwin,精度是关键,我明白,但你确实收到了我所要求的基本要点,对吗?
  • 我认为它与其他关于在 Python 中排序字典的问题非常接近,这些问题有很多很好的答案;不过,我并没有对你投反对票。
  • 好的,我添加了那个条件,因为我们正在反转排序,我们需要用 - 否定该值

标签: python sorting python-3.x dictionary


【解决方案1】:

使用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)

【讨论】:

    【解决方案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,ya,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"]

    首先获取每个字符的序号:

    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]
    

    lambda 中的xgroups.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

    【讨论】:

    • Tick: In[38] 一击解决了所有 3 个问题。你非常了解你的 Python!谢谢你。我会重命名一些东西,这样它看起来就不会太模糊了。我可以学习和理解这一点。如果我有问题,我一定会发表评论。谢谢。
    • 当我回到比赛时我会添加更多
    • lambda 之后的几乎所有内容。因为我知道 lambda 是一个匿名函数,而 x 是它的参数。
    • >>> ords = [list(map(ord,x.split(","))) for x in keys] 不起作用。显然 map 不能接受它传递的参数。 TypeError: ord() expected a character, but string of length 6 found。但是,如果没有这种代码,它会使用最大的字母,因此“xys”会胜过“asdz”(同时使用 min 而不是 -max)(像往常一样,我很快按回车键)
    【解决方案3】:

    按您需要的“人数”排序

    >>> 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 键。考虑一个不同的数据结构,例如一个字典列表:

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

    【讨论】:

    • 我不喜欢元组,因为它们是不可变的——感觉就像我无法控制它们,如果我想更改内容,我将不得不继续创建新的元组......
    • @mastercork889: 嗯....字符串同样是不可变的——你因此讨厌它们吗?
    • 我想我不能“讨厌”元组。我只是还没有完全学会如何使用它们。我想如果你把一个字符串变成一个列表,它可以被变异,然后推回一个字符串。
    • 可怕的东西,list/dictionary-inception 是。我将如何获得价值?组[0][成员][1] = 酒吧?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-08
    • 2013-05-27
    • 1970-01-01
    • 2013-12-26
    • 2022-11-18
    • 2020-12-10
    • 1970-01-01
    相关资源
    最近更新 更多