python 的sort, sorted,lambda

想写这篇文章是由largest-number这道题引起的。

question:

给你一个列表,类似于[3, 30, 34, 5, 9, 36].你把这些数拼成一个最大的数的字符串,即"953634330“即可

建议自己思考之后再继续朝后看。

---------------------------------------分割线--------------------------------------------

可能猛的一看,这个题好像很好做。只需要按字符串进行排序即可。但是!!!如果你通过字符串的方式进行了排序,可能排序完的结果就变成这样了。[“9”, “5”, “34”, “30”, “3”] 很明显,我们想要的是3排在30的前面。这样不对。那应该根据每个字符的长度吗?也不对,因为34要排在3的前面。怎么做?

不管怎么弄,都得排序。不打算自己排。我就准备用sorted.其实用sort也行。但我还是选用sorted. why?

这里得说明一下sorted 和sort的区别。

list.sort()只针对于list才能排序。不信你可以对dict试一下,dict就不行了。sorted则比较全能,字典列表元组都能排序。关键是,我的第一反应是用sorted里面的cmp这个参数来排序。

这里又有知识点了。

python2里面的sorted才有cmp这个参数,到了python3,这个参数就被砍掉了!!!

google查了一下,主要是为了防止这个cmp和自带的cmp产生冲突。所有砍掉了它.那怎么解决这个问题? 就得用from functools import cmp_to_key里面的cmp_to_key了,因为python2.7为了兼容python3,增加了它。在python3里面,就只能用它也解决sorted里面cmp的问题了。

cmp有了,写一个函数实现一下这个函数,传递给key就完成任务了。怎么弄?
要判断 34, 3, 30这个几个数的顺序。我们要做的就是两个两个比较。如果343>334,那顺序就是34, 3. 如果330>303,那么顺序就是3, 30. 所以这个函数用lambda就能完成。

key=cmp_to_key(lambda x, y: int(y+x), int(x+y))

然后把这个参数传递给sorted里面的key,就完成了排序。但是如果只是这样的话。这道题可能还是过不去,因为[0, 0]这种情况,你会返回"00",而你应该返回的是"0".
所以还要做一个lstrip(“0”) 如果是空串,就得返回"0"才行。

这个题解到这里就差不多了。但是我的表演才刚刚开始~~

先来看看被替换为cmp_to_key的cmp是什么意思。
cmp 就是比较传入的两个值x,y 如果x< y, 返回-1. 如果x>y, 返回1. 如果x=y, 返回0.一个lambda就能把两个值给准备好,传递进来就能比较了。但是到底是怎么比较的?这需要打印更多的消息,同时,我们不能用lambda. 这里我举一个例子。

import functools


class SortNumber:

    def __init__(self, val):
        self.val = val

    def __str__(self):
        return 'SortNumber({})'.format(self.val)


def compare_obj(a, b):
    if int(str(a.val) + str(b.val)) < int(str(b.val) + str(a.val)):
        print('comparing {} and {}, a<b'.format(a, b))
        return 1
    elif int(str(a.val) + str(b.val)) > int(str(b.val) + str(a.val)):
        print('comparing {} and {}, a>b'.format(a, b))
        return -1
    else:
        print('comparing {} and {}, a=b'.format(a, b))
        return 0

# get_key = functools.cmp_to_key(lambda x, y: int(str(y.val) + str(x.val)) - int(str(x.val) + str(y.val)))
get_key = functools.cmp_to_key(compare_obj)


def get_key_wrapper(o):
    "Wrapper function for get_key to allow for print statements."
    new_key = get_key(o)
    print('key_wrapper({}) -> {!r}'.format(o, new_key))
    return new_key


Input = [3, 30, 34, 5, 9, 36]   # [9, 5, 36, 34, 3, 30]
sn = [SortNumber(x) for x in Input]

for o in sorted(sn, key=get_key_wrapper):
    print(o)
result:
key_wrapper(SortNumber(3)) -> <functools.KeyWrapper object at 0x7f34d4e70d30>
key_wrapper(SortNumber(30)) -> <functools.KeyWrapper object at 0x7f34d40198b0>
key_wrapper(SortNumber(34)) -> <functools.KeyWrapper object at 0x7f34d4019ad0>
key_wrapper(SortNumber(5)) -> <functools.KeyWrapper object at 0x7f34d4019ab0>
key_wrapper(SortNumber(9)) -> <functools.KeyWrapper object at 0x7f34d4019a90>
key_wrapper(SortNumber(36)) -> <functools.KeyWrapper object at 0x7f34d4019a70>
comparing 303 < 330, 1
comparing 3430 > 3034, -1
comparing 3430 > 3034, -1
comparing 343 > 334, -1
comparing 53 > 35, -1
comparing 534 > 345, -1
comparing 93 > 39, -1
comparing 934 > 349, -1
comparing 95 > 59, -1
comparing 3634 > 3436, -1
comparing 365 < 536, 1
SortNumber(9)
SortNumber(5)
SortNumber(36)
SortNumber(34)
SortNumber(3)
SortNumber(30)

运行一下,我们大概就能看到sorted里面的key是如何遍历的了。但是这里我确实没看明白到底是怎么做的。怎么办?
这里就需要了解python里面的sorted是怎么做的了。sorted使用的排序,不是快排,不是归并。而是一个更快的,性能更好的timsort.

Timsort是结合了合并排序(merge sort)和插入排序(insertion sort)而得出的排序算法,它在现实中有很好的效率。这个暂时还没具体研究,学习后再来分享。
最后了再分享一下lambda.
lambda 就是一个很简单的函数。

example:
a = lambda x,y:x+y
print(a(2,3))   # 这里的x,y是传入的参数,x+y是最终返回值。也可以没有输入只有输出。

参考:

https://blog.csdn.net/huangmx1995/article/details/53174366?locationNum=3&fps=1
https://github.com/qiwsir/algorithm/commit/68f1af0cfe3df4a96abc528cd324f5f69f4eb9d
https://blog.csdn.net/yangzhongblog/article/details/8184707
https://www.jb51.net/article/57678.htm
https://blog.csdn.net/weixin_40156487/article/details/82460854
### Python 中 `sort` 函数结合 `lambda` 表达式的用法 在 Python 中,列表对象的 `.sort()` 方法以及内置函数 `sorted()` 都支持通过参数 `key` 来指定自定义排序逻辑。当使用 `lambda` 表达式作为 `key` 参数时,可以通过简洁的方式实现复杂的排序需求。 #### 基本概念 - **Lambda 表达式**: 是一种匿名函数,通常用于创建简单的、临时性的函数[^1]。其语法形式为:`lambda 输入变量: 返回值表达式`。 - **SortSorted 的区别**: - `.sort()` 方法会对原列表进行就地修改,不返回新列表[^2]。 - `sorted()` 函数则会生成并返回一个新的已排序列表,而不会影响原始数据结构[^2]。 #### 使用场景与示例 ##### 场景 1: 对简单列表按长度降序排列 如果有一个字符串列表,并希望按照每个字符串的长度从大到小排序,则可以如下操作: ```python cars = ['Ford', 'Mitsubishi', 'BMW', 'VW'] cars.sort(reverse=True, key=lambda x: len(x)) print(cars) ``` 这里,`lambda x: len(x)` 定义了一个匿名函数,它接受单个输入 `x` 并返回该字符串的长度。`reverse=True` 则表示结果应以降序显示[^2]。 ##### 场景 2: 处理元组列表中的次级键排序 假设有一系列商品及其价格组成的元组列表,需要依据价格升序排列这些项目: ```python items = [('Products1', 10), ('Products2', 9), ('Products3', 13)] items.sort(key=lambda item: item[1]) print(items) ``` 此代码片段利用了 `lambda item: item[1]` 这样的表达方式来提取每项记录的价格字段作为比较基础。 ##### 场景 3: 综合多种条件下的复杂排序 有时可能面临更加复杂的排序情况,比如混合不同类型的数据或者考虑多个维度上的优先级顺序。下面的例子展示了如何先判断某个元素是否为空再决定其他属性的重要性: ```python seq = [None, 7, 'apple', 42, '', [], {}, set()] result = sorted(seq, key=lambda x: (x is not None, '' if isinstance(x, Number) else type(x).__name__, x)) print(result) ``` 这段程序首先检查每一个成员是不是 `NoneType`, 接着区分数值型与其他类别最后才是具体数值本身来进行综合考量后的整体安排[^3]。 ### 总结 通过对上述不同实例的学习可以看出,在实际开发过程中灵活运用好 `lambda` 结合 `sort/.sorted` 能够极大地提升编码效率同时也让我们的解决方案变得更加优雅直观。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值