如何使用键函数在python中按填充字符串属性进行排序

时间:2015-04-26 14:12:21

标签: python sorting

假设l是具有String属性x的类c的对象列表。 l应根据以下标准进行排序: 对于任何两个项目:在最后一个斜杠字符处拆分x,取后缀,在两个前面添加一个零填充,使它们的长度相等,并按字母顺序进行比较。 我读到应该使用key函数在python中进行排序。但是,我无法通过这种方式找出达到所需排序标准的方法。如果关键功能不是实现所需排序的正确方法,我很高兴使用"正确"方式。

1 个答案:

答案 0 :(得分:1)

使用关键功能这有点棘手;使用自定义比较功能会更容易。 Python 2支持sort的自定义比较函数,但Python 3不支持。但是,使用键功能进行排序比使用自定义比较功能更有效 :键功能仅对列表中的每个项调用一次,而必须为每次比较。

" key"解决这个问题的方法是要认识到,每个字符串前面加上多少个零并不重要,只要比较的两个字符串的长度相等即可。所以我们只需要确定数据中最长字符串的长度,并将所有字符串填充到该长度。

要确定该长度,我们可以使用一个相对简单的生成器表达式,该表达式使用rsplit来获取最终斜杠后字符串部分的长度,并将这些长度传递给内置{{1}功能。然后我们可以在关键函数中使用最大长度。

以下代码适用于Python 2,但如果您在max函数中修复了print语句,它将适用于Python 3。

show

<强>输出

#!/usr/bin/env python

data = [
    'a/bc/this',
    'a/bc/is',
    'a/bc/a',
    'a/bc/short',
    'a/bc/test',
    'a/bc/123',
    'a/bc/24',
    'a/bc/5',
]

#Simple sequence printer
def show(seq):
    for row in seq:
        print row
    print

#Get maximum length of the string after the last slash in each data string
maxlen = max(len(s.rsplit('/', 1)[1]) for s in data)

#Key function that pads the string after the last slash
key = lambda s: s.rsplit('/', 1)[1].rjust(maxlen, '0')

#Test the key function
show([(s, key(s)) for s in data])

new_data = sorted(data, key=key)
show(new_data)

我不知道Timsort如何使用关键功能进行排序的具体细节,但它相当于:

  1. 将项目列表转换为(键,项目)元组列表。
  2. 对元组列表进行排序,仅对键和键进行排序。忽略该项目。
  3. 通过从排序列表中的元组中删除项目来重建新的项目列表。
  4. 这只是一个粗略的指南,因为Timsort是用C语言编写的。