Python自定义排序及实际遇到的一些实例

写在前面,本文主要介绍Python基础排序和自定义排序的一些规则,如果都比较熟悉,可以直接翻到第三节,看下实际的笔试面试题中关于自定义排序的应用。

一、基础排序

排序是比较基础的算法,与很多语言一样,Python也提供了对列表的排序方法和内建排序函数。

1、两种排序方式

方式一:

li = [1, 3, 4, 9, 0]
li.sort()  # 提供方法

方式二:

li = [1, 3, 4, 9, 0]
li = sorted(li)  # 提供方法

列表元素的排序可以通过这两种方式实现,从接受的参数可以更好地看出两者之间的区别和相似之处。

[En]

The sorting of list elements can be achieved in both ways, and the differences and similarities between the two can be better seen from the accepted parameters.

  • sort(key=None, reverse=False)
  • sorted(iterable, key, reverse)

2、不同点

(1): sort()属于列表对象特有的排序方法,因此调用方法直接在列表本身进行修改,返回值为 None或者说无需返回值。
(2): sorted()属于python提供内建函数,无需导入可直接用,而从接受对象来看, sorted()方法可以直接接受 iterable可迭代对象,因此作用对象更广泛,包括字符串,元组甚至字典都可以,返回一个列表,如下所示

test_string = "dvsegh"
print(sorted(test_string)) # 输出['d', 'e', 'g', 'h', 's', 'v']
test_tuple = (5, 4, 3, 2, 1)
print(sorted(test_tuple)) # 输出[1, 2, 3, 4, 5]
test_list = [5, 4, 3, 2, 1]
print(sorted(test_list)) # 输出[1, 2, 3, 4, 5]
test_dic = {1:"a", 2:"b", 0:"z"}
print(sorted(test_dic)) # 输出[0, 1, 2],字典的key作为排序结果返回

(3):对于Python3.x中的 sort()无法函数自定义排序规则后面会说到。

3、相同点

(1):都支持 reverse反转操作,参数 reverse接收布尔类型,比如 reverse=True,则表示排序结果逆序。

li = [1, 3, 4, 9, 0]
li.sort(reverse=True)
print(li)  # [9, 4, 3, 1, 0]

(2): 都支持关键函数排序,也就是 key参数指定排序规则,参数的接收值为一个函数,该函数可以接收一个参数并返回一个值用来比较,如下, len接收字符串,返回长度作为比较值。

test_string = "Hello World Welcome to My City"
print(sorted(test_string.split(" "), key=len))  # 根据字符串长度排序
输出:['to', 'My', 'City', 'Hello', 'World', 'Welcome']
print(sorted(test_string.split(" "), key=str.lower))  # 根据小写之后的字典序排序 
输出:['City', 'Hello', 'My', 'to', 'Welcome', 'World']

test_list = [-5, 4, 0, 2, 1]
print(sorted(test_list, key=abs))  # 根据绝对值排序 
输出:[0, 1, 2, 4, -5]

(3):更广泛的可以使用 lambda表达式来完成更复杂排序。如下对二维列表多级排序

li = [
    [3 ,5],
    [5 ,0],
    [5 ,6],
    [3 ,-1],
    [2, 9]
]
多级排序
根据第一个元素从小打到排列,当第一个元素相等,按照第二个元素从大到小排列
li.sort(key=lambda x: (x[0], -x[1]))
print(li)
 输出 [[2, 9], [3, 5], [3, -1], [5, 6], [5, 0]]

或者,您可以按复杂对象的某些属性进行排序。按属性对对象进行排序

[En]

Or you can sort by some properties of complex objects. Sort objects by attributes

学生对象,包括年龄,身高体重等
class Student:
    def __init__(self, age, height, weight):
        self.age = age
        self.height = height
        self.weight = weight

s1 = Student(18, 180, 75)
s2 = Student(19, 175, 80)
s3 = Student(17, 176, 70)
s4 = Student(18, 177, 65)
s5 = Student(19, 180, 65)

班级里有很多学生
classes = [s1, s2, s3, s4, s5]
根据学生的年龄排序
classes.sort(key=lambda s: s.age)
for stu in classes:
    print("stu age: %d, height: %d, weight: %d" % (stu.age, stu.height, stu.weight))

输出:
stu age: 17, height: 176, weight: 70
stu age: 18, height: 180, weight: 75
stu age: 18, height: 177, weight: 65
stu age: 19, height: 175, weight: 80
stu age: 19, height: 180, weight: 65

从以上排序结果中相同年龄的学生还保持排序前的相对顺序,说明 sort()排序也是稳定排序, sort()底层是基于合并排序和插入排序集合的一种更高效排序算法。以上是使用 lambda表达式指定排序规则,也可以使用 operator中提供的其他更加简洁的方式。

同样适用上述的Student例子
from operator import itemgetter, attrgetter

实现根据学生年龄排序
print(sorted(classes, key=attrgetter('age')))
print(sorted(classes, key=itemgetter(1)))
实现多级排序 新根据身高,再根据年龄排序
sorted(classes, key=attrgetter('height', 'age'))

二、排序进阶

其他语言中普遍提供的有cmp函数,也就是自定义更高级函数作为排序规则。而在python3.x中 sort()不在支持cmp自定义函数比较,想要使用cmp,则需要是使用 sorted(),并额外的做一些包装。

1、举例

比如,同样使用如上的Student例子,想要完成自定义排序规则,比如首先按照年龄大小排序,当年龄相同的时候按照体重逆序排序,如果体重也相同则按照身高逆序排序。

from functools import cmp_to_key

def func(stu1, stu2):
    # 年龄相同
    if stu1.age == stu2.age:
        # 体重相同 安装身高逆序
        if stu1.weight == stu2.weight:
            return stu2.height - stu1.height
        else: # 体重不同,逆序排序
            return stu2.weight - stu1.weight
    else: # 年龄不同,则按照年龄排序
        return stu1.age - stu2.age

class Student:
    def __init__(self, age, height, weight):
        self.age = age
        self.height = height
        self.weight = weight

s1 = Student(18, 180, 55)
s2 = Student(19, 175, 80)
s3 = Student(17, 162, 70)
s4 = Student(18, 177, 65)
s5 = Student(19, 180, 65)
s6 = Student(16, 160, 55)
s7 = Student(17, 164, 70)

班级有7个学生
classes = [s1, s2, s3, s4, s5, s6, s7]
排序
classes = sorted(classes, key=cmp_to_key(func))
for stu in classes:
    print("stu age: %d, height: %d, weight: %d" % (stu.age, stu.height, stu.weight))

输出结果
stu age: 16, height: 160, weight: 55
stu age: 17, height: 164, weight: 70
stu age: 17, height: 162, weight: 70
stu age: 18, height: 177, weight: 65
stu age: 18, height: 180, weight: 55
stu age: 19, height: 175, weight: 80
stu age: 19, height: 180, weight: 65

对于 sorted(iterable, key=lambda x:x),这种比较倾向于待排序的每个元素都有一个绝对的大小值作为排序标准,而有时候会绝对大小是根据两个元素才能得出的衡量,因此可以使用如上 functools.cmp_to_key构建多个元素的比较函数。 cmp_to_key包装后的自定义比较函数可以接受两个元素,将两个元素的对比结果作为返回值,另外注意,自定义的比较函数返回值需要是整型。

2、源码

cmp_to_key的源码如下

def cmp_to_key(mycmp):
    """Convert a cmp= function into a key= function"""
    class K(object):
        __slots__ = ['obj']
        def __init__(self, obj):
            self.obj = obj
        def __lt__(self, other):
            return mycmp(self.obj, other.obj) < 0
        def __gt__(self, other):
            return mycmp(self.obj, other.obj) > 0
        def __eq__(self, other):
            return mycmp(self.obj, other.obj) == 0
        def __le__(self, other):
            return mycmp(self.obj, other.obj) <= 0 def __ge__(self, other): return mycmp(self.obj, other.obj)>= 0
        __hash__ = None
    return K
</=>

cmp_to_key接收 myfunc,并在内部定义一个K类并返回这个K类,这个类内部完成了各种比较运算符的重载(也就是mycmp的定义的排序规则),这个类是可调用的,在参与比较的时候其实是K的对象,而在使用 lambda匿名表达式的时候使用是列表中的元素进行大小比较。如下:

li = [1, 0, 0, 8, 4]
sorted(li, key=lambda x: x)  # x&#x4EE3;&#x6307;li&#x4E2D;&#x7684;&#x6BCF;&#x4E2A;&#x5143;&#x7D20;

三、真题

以下是关于书面面试中遇到的一些自定义排序规则的一些问题。可以结合实际场景来做应用。

[En]

Here are some questions about some custom sorting rules encountered during the written interview. Can be combined with the actual scene to do the application.

:以下只给出大概代码样例,水平有限,不保证完全正确。

1、题目一

(1): 华为通用软件暑期实习笔试4.13场次算法题第一题
题干:硬件资源分配(不花点时间,题干都理不顺…..)
有M台服务器,每台服务器有以下属性:编号、CPU核数(1100)、内存、CPU架构(08)、是否支持NP加速的标识(0,1)。然后有一个资源分配要求,要求分配N台满足要求的服务器。具体如下:CPU核数>=cpuCount、内存>=memSize、CPU架构=cpuArch、是否支持NP加速=supportNP。其中,cpuCount、memSize、cpuArch、supportNP为这个要求输入的分配参数。
分配时指定优先级策略。政策如下:

[En]

A priority policy is specified when assigning. * the policy is as follows:

策略1:CPU优先,优先选择CPU核数满足分配要求并且最接近分配要求的cpuCount。如果CPU核数相同,在按内存满足要求并选择最接近memSize的服务器分配。
策略2:内存优先,优先选择内存满足分配要求并且最接近分配要求的memSize。如果内存相同,在按cpu核数满足要求并选择最接近cpuCount的服务器分配
如果两台服务器的属性相同,请按服务器编号从小到大选择(编号不会重复)

[En]

If the attributes of both servers are the same, select by server number from small to large (the number will not be duplicated)*

输入**:
第一行:服务器数量M
接下来M行为M台服务器属性的数组
下一行为分配要求:最大分配数量N,分配策略strategy,cupCount,memSize,cpuArch,supportNP
其中:
1

&#x8F93;&#x5165;
4
0,2,200,0,1
1,3,400,0,1
2,3,400,1,0
3,3,300,0,1
3 1 3 200 0 1
&#x8F93;&#x51FA;
2 1 3
&#x89E3;&#x91CA;&#xFF1A;&#x53EA;&#x6709;1&#x548C;3&#x6EE1;&#x8DB3;&#x8981;&#x6C42;&#xFF0C;&#x8981;&#x6C42;&#x5206;&#x914D;2&#x53F0;&#x670D;&#x52A1;&#x5668;&#xFF0C;&#x6240;&#x4EE5;&#x7ED3;&#x679C;&#x4E3A;2 1 3

样例2

&#x8F93;&#x5165;
6
0,2,200,0,1
1,4,330,2,1
2,3,400,3,1
3,3,310,1,1
4,3,320,8,1
5,3,330,0,1
3 2 3 300 9 2
&#xFF08;&#x8FD9;&#x91CC;&#x6CE8;&#x610F;&#x4E00;&#x4E0B;&#x8F93;&#x5165;&#x7684;&#x683C;&#x5F0F;&#xFF0C;&#x6700;&#x540E;&#x4E00;&#x884C;&#x662F;&#x7A7A;&#x683C;&#x5206;&#x5F00;&#xFF09;
&#x8F93;&#x51FA;
3 3 4 5
&#x89E3;&#x91CA;&#xFF1A;&#x7F16;&#x53F7;1~5&#x90FD;&#x6EE1;&#x8DB3;&#x5206;&#x914D;&#x8981;&#x6C42;&#xFF0C;&#x6309;&#x7B56;&#x7565;2&#x5206;&#x914D;&#x5373;&#x5185;&#x5B58;&#x4F18;&#x5148;&#xFF0C;&#x5185;&#x5B58;>=300&#x5E76;&#x4E14;&#x6700;&#x63A5;&#x8FD1;300&#x7684;&#x670D;&#x52A1;&#x5668;&#x7F16;&#x53F7;&#x662F;3 4 1 5 2&#x3002;
&#x5176;&#x4E2D;1&#x548C;5&#x5185;&#x5B58;&#x76F8;&#x540C;&#xFF0C;&#x7136;&#x540E;&#x4F1A;&#x6BD4;&#x8F83;CPU&#xFF0C;&#x5373;CPU>=3&#x4E14;&#x6700;&#x63A5;&#x8FD1;&#x7684;&#xFF0C;&#x6240;&#x4EE5;5&#x4F18;&#x5148;&#x4E8E;1.&#x56E0;&#x6B64;&#x6700;&#x540E;&#x5206;&#x914D;&#x7684;&#x4E09;&#x53F0;&#x670D;&#x52A1;&#x5668;&#x662F;3 4 5&#x3002;
&#x8F93;&#x51FA;&#x65F6;&#x5148;&#x8F93;&#x51FA;&#x6570;&#x91CF;3&#xFF0C;&#x518D;&#x6309;&#x7F16;&#x53F7;&#x6392;&#x5E8F;&#x8F93;&#x51FA;3 4 5

(2) 思路自定义排序
主要是先考虑一些特殊情况,不同的政策有不同的排序规则,但都是相似的。

[En]

Mainly consider some special cases first, and different policies have different sorting rules, but they are all similar.

inp = list(map(int, input().strip().split(" ")))
N, strategy, cpuCount, memSize, cpuArch, SupportNP = inp
N, strategy, cpuCount, memSize, cpuArch, SupportNP = 2, 1, 3, 300, 9, 1

res = []
for item in ans:
    if cpuArch != 9 and item[3] != cpuArch:
        continue
    if SupportNP != 2 and item[4] != SupportNP:
        continue
    res.append(item)

if strategy == 1:
    res = list(filter(lambda item: item[1]>=cpuCount and item[2]>=memSize, res))
    # res = list(filter(lambda item: item[2]>=memSize, res))
    res.sort(key=lambda x: (x[1], x[2]))

    if len(res) <= n and len(res)> 0:
        tmp = [len(res)] + sorted([item[0] for item in res])
        print(" ".join([str(i) for i in tmp]))
    elif len(res) > N:
        tmp = [N] + sorted([res[i][0] for i in range(N)])
        print(" ".join([str(i) for i in tmp]))
    else:
        print(0)

elif strategy == 2:
    res = list(filter(lambda item: item[2]>=memSize and item[1]>=cpuCount, res))
    # res = list(filter(lambda item: item[1]>=cpuCount, res))
    res.sort(key=lambda x: (x[2], x[1]))

    if len(res) <= n and len(res)> 0:
        tmp = [len(res)] + sorted([item[0] for item in res])
        print(" ".join([str(i) for i in tmp]))
    elif len(res) > N:
        tmp = [N] + sorted([res[i][0] for i in range(N)])
        print(" ".join([str(i) for i in tmp]))
    else:
        print(0)
</=></=>

2、题目二

(1)、华为通用软件暑期实习业务一面算法题
Leetcode最大数:链接https://leetcode-cn.com/problems/largest-number/
题干:
给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。
示例:
输入:nums = [3,30,34,5,9]
输出:”9534330″
(2)、三种思路
version1
由于没有看到nums数组的容量范围,第一反应直接全排列,然后对每一种结果作比较。

from itertools import permutations

nums = [3, 30, 34, 5, 9]

res = set(permutations(nums))  # &#x5168;&#x6392;&#x5217;&#x7ED3;&#x679C;&#x53BB;&#x91CD;
res = [int("".join(list(map(str, item)))) for item in res]  # &#x7ED3;&#x679C;&#x62FC;&#x63A5;&#x518D;&#x7C7B;&#x578B;&#x8F6C;&#x6362;
print(max(res))  # &#x53D6;&#x6700;&#x5927;&#x503C; &#x8F93;&#x51FA; 9534330

但是nums这么大范围,使用全排列做得无用功太多了,时间和空间复杂度都不满足。
version2
保持一个单调的队列,保证拼接后队列中元素的最大大小,逐个遍历当前元素,然后尝试逐个插入队列,最后找出插入位置的规则来保持队列。

[En]

Maintain a monotonous queue, ensure the maximum size of the elements in the queue after splicing, traverse the current elements one by one, then try to insert into the queue one by one, and finally find the rules of the insertion position to keep the queue.

class&#xA0;Solution:
&#xA0;&#xA0;&#xA0;&#xA0;def&#xA0;largestNumber(self,&#xA0;nums:&#xA0;List[int])&#xA0;->&#xA0;str:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;queue&#xA0;=&#xA0;[]
        # &#x9010;&#x4E2A;&#x904D;&#x5386;&#x5217;&#x8868;&#x5143;&#x7D20;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;for&#xA0;i&#xA0;in&#xA0;range(len(nums)):
            # &#x961F;&#x5217;&#x4E3A;&#x7A7A;&#xFF0C;&#x76F4;&#x63A5;&#x5165;&#x961F;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;len(queue)&#xA0;==&#xA0;0:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;queue.append(nums[i])
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;continue
            # &#x5047;&#x5B9A;&#x5F53;&#x524D;nums[i]&#x653E;&#x5728;&#x961F;&#x5C3E;&#xFF0C;&#x62FC;&#x63A5;&#x540E;&#x7684;&#x503C;&#x4E3A;mx
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;mx_ind&#xA0;=&#xA0;-1
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;mx&#xA0;=&#xA0;int("".join(list(map(str,&#xA0;&#xA0;queue&#xA0;+&#xA0;[nums[i]]))))
            # &#x9010;&#x4E2A;&#x63D2;&#x5165;&#x961F;&#x5217;&#x4E2D;&#xFF0C;&#x4F5C;&#x6BD4;&#x8F83;&#xFF0C;&#x8C01;&#x5927;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;for&#xA0;j&#xA0;in&#xA0;range(len(queue)):
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;tmp&#xA0;=&#xA0;int("".join(list(map(str,&#xA0;&#xA0;queue[:j]&#xA0;+&#xA0;[nums[i]]&#xA0;+&#xA0;queue[j:]))))
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;tmp&#xA0;>&#xA0;mx:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;mx&#xA0;=&#xA0;tmp
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;mx_ind&#xA0;=&#xA0;j
            # &#x627E;&#x5230;&#x63D2;&#x5165;&#x4F4D;&#x7F6E;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;mx_ind&#xA0;!=&#xA0;-1:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;queue&#xA0;=&#xA0;queue[:mx_ind]&#xA0;+&#xA0;[nums[i]]&#xA0;+&#xA0;queue[mx_ind:]
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;else:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;queue&#xA0;=&#xA0;queue[:]&#xA0;+&#xA0;[nums[i]]
        # &#x5408;&#x5E76;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;st&#xA0;=&#xA0;"".join(list(map(str,&#xA0;queue)))
        # &#x53BB;&#x9664;&#x9996;&#x90E8;0
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;st = st.lstrip("0")
        # &#x5982;&#x679C;&#x5168;&#x4E3A;0&#xFF0C;&#x5982;nums=[0, 0]&#xFF0C;&#x5219;&#x8F93;&#x51FA;0
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;len(st)&#xA0;==&#xA0;0:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;"0"
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;else:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;st

执行结果:

Python自定义排序及实际遇到的一些实例

version3
nums中的元素的位置不是由单一的元素决定,而是根据两个元素拼接之后的谁大决定的,如果”xy” > “yx”,那就[x, y],否则[y, x]。因此可以使用自定义排序。

class&#xA0;Solution:
&#xA0;&#xA0;&#xA0;&#xA0;def&#xA0;largestNumber(self,&#xA0;nums:&#xA0;List[int])&#xA0;->&#xA0;str:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;from&#xA0;functools&#xA0;import&#xA0;cmp_to_key
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;def&#xA0;func(a,&#xA0;b):
            # &#x5F53;&#x524D;&#x4E24;&#x5143;&#x7D20;&#x957F;&#x5EA6;&#x76F8;&#x7B49;&#xFF0C;&#x5219;&#x6309;&#x7167;&#x5927;&#x5C0F;&#x6392;&#x5217;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;len(str(a))&#xA0;==&#xA0;len(str(b)):
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;b&#xA0;-&#xA0;a
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;else:
            # &#x957F;&#x5EA6;&#x4E0D;&#x540C;&#xFF0C;&#x5219;&#x6839;&#x636E;&#x62FC;&#x63A5;&#x540E;&#x7684;&#x5927;&#x5C0F;&#x6392;&#x5E8F;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;int(str(b)+str(a))&#xA0;-&#xA0;int(str(a)+str(b))&#xA0;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;nums&#xA0;=&#xA0;sorted(nums,&#xA0;key=cmp_to_key(func))

        # &#x7A81;&#x7136;&#x53D1;&#x73B0;&#x8FD9;&#x6837;&#x5199;&#x66F4;&#x7B80;&#x6D01; &#xFF0C;&#x4E0D;&#x7528;&#x989D;&#x5916;&#x5B9A;&#x4E49;func
        # nums&#xA0;=&#xA0;sorted(nums,&#xA0;key=cmp_to_key(lambda&#xA0;x,&#xA0;y:&#xA0;int(str(y)+str(x))&#xA0;-&#xA0;int(str(x)+str(y))))

&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;s&#xA0;=&#xA0;"".join(list(map(str,&#xA0;nums)))
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;s&#xA0;=&#xA0;s.lstrip("0")
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;len(s)&#xA0;!=&#xA0;0:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;s
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;else:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;"0"

执行结果:

Python自定义排序及实际遇到的一些实例

3、题目三

(1)、荣耀通用软件暑期开发实习生笔试第二题
标题不是很清楚,大概是把日志文件中的一行记录按照时间戳进行排序,记录是一个字符串,但整条记录包含了其他一些无用的字符串,所以要过滤掉有用的时间戳。

[En]

The title is not very clear, probably is to sort one line of records in the log file according to the timestamp, the record is a string, but the whole record contains some other useless strings, so you have to filter out the useful timestamps.

实例输入:

5
my/2019-01-01T09:00:01
my/2019-01-01T09:00:01
abc/2018-12-24T08:00:00/test/you
1/2018-12-24T08:00:00/test/Test1
123/2018-12-24T08:00:09/test/me

说明:5表示5行记录
输出:

1/2018-12-24T08:00:00/test/Test1
abc/2018-12-24T08:00:00/test/you
123/2018-12-24T08:00:09/test/me
my/2019-01-01T09:00:01

说明:优先根据时间戳信息排序,时间戳满足一定的格式XXXX-XX-XXTXX:XX:XX,T为分隔符,分割日期和时间,前半部分为日期,后半部分为时间,时间戳相同根据字符串长度排序,如果长度也相同,则按照首字母的ascii码表比较从小到大排序,如果两个记录字符串完全相同,则输出一条即可。
(2)、思路
它主要是一个自定义排序规则,但需要对所有记录进行处理,以确定它们是否符合时间戳规则并删除重复项。

[En]

It is mainly a custom collation, but all records need to be processed to determine whether they meet the timestamp rule and to remove duplicates.

代码如下

from functools import cmp_to_key

&#x5224;&#x65AD;&#x8BB0;&#x5F55;&#x5B57;&#x7B26;&#x4E32;&#x662F;&#x5426;&#x7B26;&#x5408;&#x65F6;&#x95F4;&#x6233;&#x683C;&#x5F0F;
def is_time_format(s):
    if len(s) != 19:
        return False
    if s[4] != "-"  or s[7] != "-" or s[10] != "T" or s[13] != ":" or s[16] != ":":
        return False
    return True

&#x81EA;&#x5B9A;&#x4E49;&#x6392;&#x5E8F;&#x89C4;&#x5219;
def func(a, b):
    if a[0] != b[0]:
        if a[0] > b[0]:
            return 1
        else:
            return -1
    else:
        if len(a[1]) != len(b[1]):
            return len(a[1]) - len(b[1])
        else:
            return ord(a[1][0]) - ord(b[1][0])

&#x5904;&#x7406;&#x8F93;&#x5165;
size = int(input().strip())
time_str = []
for _ in range(size):
    # &#x5E76;&#x5C06;&#x8BB0;&#x5F55;&#x5206;&#x5272;&#x6210;&#x5217;&#x8868;&#x6682;&#x5B58;&#x8D77;&#x6765;
    tmp = input().strip().split("/")
    time_str.append(tmp)

&#x4FDD;&#x5B58;&#x6EE1;&#x8DB3;&#x65F6;&#x95F4;&#x6233;&#x7684;&#x8BB0;&#x5F55;
res = []
for i in range(len(time_str)):
    for j in range(len(time_str[i])):
        if is_time_format(time_str[i][j]):
            res.append([time_str[i][j],  "/".join(time_str[i])])
            break
res = sorted(res, key=cmp_to_key(func))  # &#x81EA;&#x5B9A;&#x4E49;&#x6392;&#x5E8F;

&#x91CD;&#x5851;&#x7ED3;&#x679C;
ans = []
for i in range(len(res)):
    if res[i][1] not in ans:
        ans.append(res[i][1])

&#x5904;&#x7406;&#x8F93;&#x51FA;
print("\n".join(ans))

Original: https://www.cnblogs.com/welan/p/16243852.html
Author: weilanhanf
Title: Python自定义排序及实际遇到的一些实例

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/499644/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球