1

我们知道这两种方法都适用于 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))

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

4

1 回答 1

1

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

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

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

这是一些代码:

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它的返回值(aka key_func)是作为key参数传递给sorted.

于 2013-09-27T11:14:29.163 回答