【问题标题】:How to apply key function on tuple elems in sorted()?如何在 sorted() 中对元组元素应用键函数?
【发布时间】:2013-10-03 14:45:28
【问题描述】:

我们知道这两种方法都适用于 sorted():

sorted(['second', 'first', 'third'])
sorted([('first','second'), ('second', 'first'), ('first', 'third')])

通过对第二个进行排序,元组按字典顺序进行比较;比较第一个项目;如果它们相同,则比较第二个项目,依此类推。

但是如何在所有单独的字符串(或其他任何字符串)上应用一个 key 函数来进行排序,它适用于容器并在第二种情况下递归地工作?假设 func 将“first”转换为 3,将“second”转换为 1,将“third”转换为 2。我想要这个结果:

['second', 'third', 'first']
[('second', 'first'), ('first','second'), ('first', 'third')]

我将此函数用作键,但我不喜欢在其中进行类型检查,因为它仅将 func 应用于不是通用解决方案的字符串:

def recursively_apply_func_on_strings(target, func,
    fargs=(), fkwargs={}):
    if isinstance(target, str):
        return func(target, *fargs, **fkwargs)       
    result, f = [], recursively_apply_func_on_strings
    for elem in target:
        result.append(f(elem, func, fargs, fkwargs))
    return tuple(result)

sorted(sequence, key=lambda x: recursively_apply_string_func(x, func))

有没有更简洁的方法来做到这一点?

【问题讨论】:

  • 我认为没有比您拥有的更好的算法了。您可以使用 tuple 构造函数中的生成器表达式使代码更好一些,而不是将值逐个附加到结果中,但这是我唯一能看到改进的地方。如果您不喜欢检查str,请考虑在任何字符串或任何不可迭代的字符串上调用func(您希望从递归案例中排除字符串,因为它们可以永远递归迭代)。使用isinstance(target, collections.Iterable) 测试可迭代类型。
  • 感谢您指出这一点,有时我想念使用它们,生成器表达式。 :)

标签: function sorting python-3.x tuples


【解决方案1】:

好吧,尽管我的评论另有说法,但我认为有一些可能的方法可以改进。

一个想法是让你的函数成为一个关键函数工厂。这样,您就不需要 lambda 来在您的 sorted 调用中使用额外的参数来应用它。

另一个想法是将func 应用于所有不可迭代的值(加上字符串),使用来自collections 模块的抽象Iterable 类型进行测试。

这里有一些代码:

from collections import Iterable

def recursive_key(func, fargs=(), fkwargs={}):
    def key_func(target):
        if isinstance(target, str) or not isinstance(target, Iterable):
            return func(target, *fargs, **fkwargs)       
        return tuple(key_func(item) for item in target)
    return key_func

你可以这样称呼它(按十六进制整数值排序,而不是字符串值):

sorted([('a', 'F'), ('A', 'd')], key=recursive_key(int, (16,)))

请注意,我们调用 recursive_key,它的返回值(也称为key_func)是作为key 参数传递给sorted 的值。

【讨论】:

  • 感谢您的精彩代码!我所做的唯一更改是将tuple 替换为target.__class__,这样它在列表上也能很好地工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-30
  • 1970-01-01
  • 2016-07-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多