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

    原文作者:算法
    原文地址: https://www.twblogs.net/a/5bd3bf682b717778ac20c95d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞