Function 如何在sorted()中的元组元素上应用键函数?

Function 如何在sorted()中的元组元素上应用键函数?,function,sorting,python-3.x,tuples,Function,Sorting,Python 3.x,Tuples,我们知道这两种方法都适用于排序() 通过对第二个元组进行排序,按字典顺序对元组进行比较;比较第一项;如果它们相同,则比较第二项,依此类推 但是如何在所有单独的字符串(或其他任何字符串)上应用一个键函数,以便在第二种情况下对容器和递归都有效?假设func将“first”转换为3,“second”转换为1,“third”转换为2。我想要这个结果: ['second', 'third', 'first'] [('second', 'first'), ('first','second'), ('firs

我们知道这两种方法都适用于排序()

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

但是如何在所有单独的字符串(或其他任何字符串)上应用一个键函数,以便在第二种情况下对容器和递归都有效?假设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))

有没有更干净的方法可以做到这一点?

好吧,尽管我的评论不是这样说的,但我认为有几种可能的方法可以改进事情

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

另一个想法是将
func
应用于所有不可iterable值(加上字符串),使用
collections
模块中的abstract
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
您可以这样称呼它(按十六进制整数值排序,而不是按字符串值排序):


请注意,我们正在调用
recursive\u key
,它的返回值(又称
key\u func
)是作为
key
参数传递给
sorted

的值。尽管我的评论不是这样说,但我认为有一些可能的方法可以改进

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

另一个想法是将
func
应用于所有不可iterable值(加上字符串),使用
collections
模块中的abstract
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
您可以这样称呼它(按十六进制整数值排序,而不是按字符串值排序):


请注意,我们正在调用
recursive\u key
,它的返回值(也称
key\u func
)是作为
key
参数传递给
sorted

的,我认为没有比您的算法更好的了。在
元组
构造函数中使用生成器表达式可能会使代码变得更好,而不是将值逐个添加到结果中,但这是我唯一可以改进的地方。如果您不喜欢检查<代码> STR ,请考虑在任何字符串上调用它“代码>代码FUNC< /代码>,或是不可重复的任何东西(要从递归的情况下排除字符串,因为它们是递归迭代的)。使用
isinstance(target,collections.Iterable)
测试Iterable类型。感谢您指出这一点,有时我会错过使用生成器表达式的机会。:)我认为没有比你的算法更好的了。在
元组
构造函数中使用生成器表达式可能会使代码变得更好,而不是将值逐个添加到结果中,但这是我唯一可以改进的地方。如果您不喜欢检查<代码> STR ,请考虑在任何字符串上调用它“代码>代码FUNC< /代码>,或是不可重复的任何东西(要从递归的情况下排除字符串,因为它们是递归迭代的)。使用
isinstance(target,collections.Iterable)
测试Iterable类型。感谢您指出这一点,有时我会错过使用生成器表达式的机会。:)谢谢你的代码!我所做的唯一改动是用
target替换
tuple
。\uuuuu class\uuuuu
因此它在列表上也能很好地工作。谢谢你的代码!我所做的唯一改动是用
target替换
tuple
。\uuuuu class\uuuuu
,因此它在列表上也能很好地工作。
sorted([('a', 'F'), ('A', 'd')], key=recursive_key(int, (16,)))