【问题标题】:Python custom sortPython自定义排序
【发布时间】:2015-06-12 20:22:31
【问题描述】:

我正在尝试使用 Python 的 sorted 函数对列表进行排序。在 Python 3 中,cmp 关键字参数已被删除。不幸的是,我似乎无法使用 key 关键字参数来实现我的算法,因为我需要两个对象才能比较数据。

排序数据示例

59 59
59 3 1 1
59 4 3 3
61 1
61 10
61 237
61 1 1 1

比较函数

NUM_RE = re.compile("[\d]+")
def compare(x, y):
    # Aggregate our data into integer arrays
    x_result = [int(x) for x in NUM_RE.findall(x)]
    y_result = [int(y) for y in NUM_RE.findall(y)]

    # Return if there is a non-zero difference in the first element
    statement_diff = x_result[0] - y_result[0]
    if statement_diff != 0:
        return statement_diff

    # Return if there is a non-zero difference between the lengths
    length_diff = len(x_result) - len(y_result)
    if length_diff != 0:
        return length_diff

    # len(x_result) == len(y_result)
    # Iterate over each item and return if there is a difference
    for i in range(1, len(x_result)):
        result = x_result[i] - y_result[i]
        if result != 0:
            return result

    # Results are the same
    return 0

对这些数据进行排序的最佳方法是什么?我是否应该创建一个实现__eq_____gt____lt__ 等函数的“包装器对象”,以便可以使用默认排序函数?或者标准 Python API 中是否包含另一个函数来完成 sorted 的原始行为?

【问题讨论】:

  • 你到底想做什么?我感觉它可以简化很多,min(x_result.groups(), y_result.groups()) 如何与范围一起工作?
  • 不也是NUM_RE.findall 没有群组吗?
  • 您提供的比较功能不正确。没有find_all 方法,findall 返回一个列表——不是一个匹配对象,正如您在这里所期望的那样。您能否提供一个有效的比较功能来显示您实际寻找的内容?如果比较函数实际上产生了一致的顺序,那么应该可以将其重写为key函数。
  • @senderle 抱歉,我已经修复了比较功能

标签: python sorting python-3.x


【解决方案1】:

Python 已经有了你描述的包装器,它叫做functools.cmp_to_key

【讨论】:

    【解决方案2】:

    事实上,这可以很容易地实现为一个关键功能。比较函数的行为就像字符串已转换为列表一样。所以就像将字符串转换为数字列表一样简单:

    NUM_RE = re.compile("[\d]+")
    def seq_key(x):
        return [int(y) for y in NUM_RE.findall(x)]
    

    如果您对此感到不确定,请尝试以下测试:

    cmp_key = functools.cmp_to_key(compare)
    
    def gen_rnd(n):
        seq = [[random.randrange(1, 100)
               for _ in xrange(random.randrange(2, 6))]
               for _ in xrange(n)]
        return [' '.join(map(str, x)) for x in seq]
    
    def test(n):
        a = gen_rnd(n)
        return all(sorted(x, key=seq_key) == sorted(x, key=cmp_key)
                   for x in a)
    
    test(1000000)
    

    这个测试不检查极端情况,但我很确定这些在语义上是相同的。

    您可能会问“为什么要费心找出正确的 key 函数?”原因如下:

    >>> a = gen_rnd(10000)
    >>> %timeit sorted(a, key=cmp_key)
    1 loops, best of 3: 705 ms per loop
    >>> %timeit sorted(a, key=seq_key)
    10 loops, best of 3: 47.9 ms per loop
    

    按键功能快了一个数量级以上!列表越大,效果越明显。这部分是因为列表比较是一个快速的内置功能。但这也是因为真正要做的工作更少。执行比较的次数是O(n log n),但是执行的key转换次数只有O(n)。因此,如果您可以将一些比较工作转移到一个关键功能中,您可以获得很好的加速。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-04
      • 2018-10-09
      • 2012-08-15
      • 1970-01-01
      • 2022-12-04
      • 1970-01-01
      • 2015-02-09
      相关资源
      最近更新 更多