【问题标题】:How to sort a dictionary by a value passed through a function?如何按通过函数传递的值对字典进行排序?
【发布时间】:2015-02-17 22:27:09
【问题描述】:

我有一个名为“times”的字典,它将键映射到代表时间的字符串值:

times = {'key1': '12.23', 'key2': '43:53.29', 'key3': '1:38:11.50r'}

字符串采用 [hours]:[minutes]:[seconds].[milliseconds][r] 的形式 每个字段都是可选的。 r 是一个标志,它不依赖于任何其他正在填充的值,也不影响排序。 [hours] 要求存在 [minutes] 及以下,但 [minutes] 不需要存在 [hours]。

我希望得到一个按其值的时间顺序排序的键列表。

我有以下几点:

standings = sorted(times, key=times.__getitem__)

但它仅根据字符串值进行排序。我是 python 新手,但如果我使用的是 java,我可能会编写一个带有自定义 compareTo() 函数的 Time 类来让排序工作。

我可以编写一个函数,将字符串转换为以毫秒为单位的时间,然后根据它进行排序,但不知道如何在 sorted() 函数中使用'key='。

【问题讨论】:

  • 50r 中的'1:38:11.50r' 是什么?
  • 半秒,在接力赛中(这些是比赛时间)。 'r' 只是一个标志,对排序没有任何意义

标签: python sorting dictionary lambda strptime


【解决方案1】:
import re
def as_list(time):
    """
    >>> as_list('1:38:11.50r')
    [1, 38, 11, 50]
    >>> as_list('2.23')
    [0, 0, 2, 23]
    """
    # Extract times and convert to integers
    times = [int(x) for x in re.split(r"[:.]", re.sub("[a-z]$", "", time))]
    # If needed pad from the left side with zeros and return
    return times if len(times) == 4 else [0] * (4 - len(times)) + times

[k for k, t in sorted(times.items(), key = lambda x: as_list(x[1]))]

或者更简洁的方式:

[key for _, key in sorted((as_list(v), k) for k, v in times.items())]

它之所以有效,是因为 Python 中的列表或元组是按字典顺序排序的。假设您有如下列表:

>>> l = [[0, 1], [-1 , 2, 3], [4, 5], [0, -1]]

你可以拨打sorted就可以了

>>> sorted(l)
[[-1, 2, 3], [0, -1], [0, 1], [4, 5]]

因此所有的魔法。

关于[0] * (4 - len(times)) + times,您可以在此处阅读更多信息:Create List of Single Item Repeated n Times in Python

长话短说 some_list * some_integer 创建一个列表,其中包含重复 some_integer 次的 some_list 元素。

【讨论】:

  • 看起来这行得通!我理解基于 ':' 和 '.' 的拆分,忽略任何非数字字符。你能解释一下“返回时间如果 len(times) == 4 else [0] * (4 - len(times)) + times”和“[k for k, t in sorted(times.items(), key = lambda x: as_list(x[1]))]"?
  • 你不需要\..[]不会有它的特殊含义。另外,使用原始字符串。
  • @zero323 是的,这很有帮助。谢谢!
  • @thefourtheye 已更新,谢谢。我最近在 R 上花了很多时间,我觉得我必须逃避一切,然后再一次逃避。
【解决方案2】:

您可以执行以下操作:

standings = sorted(times.items(),key = lambda t : t[0])

它假定您要按字典的键进行排序。如果要按值排序,请将 t[0] 替换为 t[1]。

请注意,我使用 t[0] 来获取对键的引用作为示例,但在您的情况下,您将引用 t[1] 但您可能会将此值传递给将时间转换为字符串的函数易于按字典顺序排序的格式。例如,假设您有一个返回填充时间的 time_format 方法,那么您将上面的 t[0] 替换为 time_format(t[1])。

【讨论】:

  • 这给了我一个排序的值列表。我需要一个按其值的函数排序的键列表。
  • 所以 {Bob: 2, Jim: 5, Billy: 3} 会产生类似 [Bob, Billy, Jim]
【解决方案3】:

我想你可以定义一个函数to_decimal将时间字符串转换为小数进行比较,那么:

standings = sorted(times, key = lambda x : to_decimal(times[x]))

【讨论】:

  • 如何转换为十进制?我不确定 1.43.23.43 是否有效
  • 我猜你需要解析字符串以确定每个部分的单位,然后求和。
  • 所以你的意思是把时间转换成毫秒然后排序?
猜你喜欢
  • 2010-10-11
相关资源
最近更新 更多