The familiar song came from afar , Why are those voices so weak . long time no see , Are you all right now ? Is there such a song , Will let you follow and , With the ups and downs of our lives , A theme song to sing together ; Is there such a song , It will remind you of me , Make you happy and worry , Such a me ……
The music is over , Back to the point . Browse recently LeetCode, I found an interesting little topic . When I try Python When you answer , Actually used the assembly 、map function 、zip function 、lambda function 、sorted function , The debugging process also involves iterators 、 generator 、 The concept of list derivation . A seemingly simple topic , Although the final code can be combined into one line , But almost put Python I used the programming skills of , It can be said. “ The subtlety is the spirit ”! Through this topic , Maybe it will make you really understand Python Programming .
This question , be known as 《 The lucky number in the list 》. What is the lucky number ? In the list of integers , If a number appears at the same frequency as its value , We call this number 「 Lucky number 」. for example , In the list [1, 2, 2, 3] in , Numbers 1 And number 2 The number of times they appear is 1 and 2, So they are lucky numbers , but 3 Only ever 1 Time ,3 It's not a lucky number .
I understand the concept of lucky number , Let's try to find out the list [3, 5, 2, 7, 3, 1, 2 ,4, 8, 9, 3] The lucky number in . This process can be divided into the following steps :
Find out the numbers that are not repeated in the list , That is, to remove duplicate elements from the list , abbreviation “ duplicate removal ”. The simplest way to de duplicate is to use sets .
>>> arr = [3,5,2,7,3,8,1,2,4,8,9,3] >>> unique = set(arr) >>> unique {1, 2, 3, 4, 5, 7, 8, 9}
We know , The list object comes with a count() Method , Can return the number of times an element appears in the list , The usage is as follows :
>>> arr = [3,5,2,7,3,8,1,2,4,8,9,3] >>> arr.count(8) # Elements 8 In the array arr There has been 2 Time 2
Next , We only need to traverse the elements after de duplication , Count the number of times they appear one by one , And save it into a suitable data structure , This step of the work will be all right .
>>> arr = [3,5,2,7,3,8,1,2,4,8,9,3] >>> unique = set(arr) # Remove duplicate elements >>> pairs = list() # An empty list , Used to hold tuples of array elements and occurrence times >>> for i in unique: pairs.append((i, arr.count(i))) >>> pairs [(1, 1), (2, 2), (3, 3), (4, 1), (5, 1), (7, 1), (8, 2), (9, 1)]
As a rookie , Code like this , Has been very good . however , A aspiring programmer will never be complacent about it 、 come to a standstill . Their favorite thing to do is to do everything possible to eliminate for loop , For example, using mapping functions 、 Filter function instead of for loop ; Even if you can't refuse for loop , They also try to hide the cycle as much as possible , For example, hiding in list derivation . Since this is to call the list for every element count() This method , That's the best way to use map Function instead of for Circulated .
>>> m = map(arr.count, unique) >>> m <map object at 0x0000020A2D090E08> >>> list(m) # Generators can be converted to lists [1, 2, 3, 1, 1, 1, 2, 1] >>> list(m) # The generator can only be used once , After use , It's automatically cleaned up []
map The function returns a generator (generator), It can be traversed like a list , But you can't see the elements as intuitively as a list , Unless we use list() Turn this generator into a list ( You don't actually need to turn the generator into a list ). Please note that , Generators are different from iterators , Or a generator is a special kind of iterator , Can only be traversed once , End of traversal , It's gone . Iterators can iterate over and over . such as ,range() Function returns iterator :
>>> a = range(5) >>> list(a) [0, 1, 2, 3, 4] >>> list(a) [0, 1, 2, 3, 4]
Say generator and iterator , We have to go back to the original topic . Use map Mapping function , We get the number of occurrences of each element , You also need to form a tuple with the corresponding elements . Now , Just use zip() Function .zip() Function to create a generator , Used to aggregate every iteratable object ( iterator 、 generator 、 list 、 Tuples 、 aggregate 、 String, etc. ) The elements of , Elements aggregate according to the same subscript , If the length is different, elements larger than the shortest iteration object length will be ignored .
>>> m = map(arr.count, unique) >>> z = zip(unique, m) >>> z <zip object at 0x0000020A2D490508> >>> list(z) [(1, 1), (2, 2), (3, 3), (4, 1), (5, 1), (7, 1), (8, 2), (9, 1)] >>> list(z) []
Obviously ,zip() The function also returns the generator , It can only be used once , Then it disappears .
With each element and its number of occurrences , We just need to loop through …… No , One moment please , Why do we have to cycle ? We just need to filter every element , Find out the tuples that have the same number of occurrences as the element itself , Why not try the filter function filter() Well ?
>>> def func(x): # Parameters x It's a tuple type if x[0] == x[1]: return x >>> m = map(arr.count, unique) >>> z = zip(unique, m) >>> f = filter(func, z) >>> f <filter object at 0x0000020A2D1DD908> >>> list(f) [(1, 1), (2, 2), (3, 3)] >>> list(f) []
Filter function filter() Take two parameters , The first 1 A parameter is a function , Used to determine whether an element meets the filtering conditions , The first 2 One parameter is the iteratable object to be filtered .filter() The function also returns the generator , It can only be used once , Then it disappears .
Write here , We're almost done . however , As a pursuing programmer , You can tolerate func() Such a strange looking function ? The answer is no ! You must be able to use lambda Function to replace it . in addition , Maybe we need to sort the results by the size of the elements . Add sorting , The complete code is as follows :
>>> arr = [3,5,2,7,3,8,1,2,4,8,9,3] >>> unique = set(arr) >>> m = map(arr.count, unique) >>> z = zip(unique, m) >>> f = filter(lambda x:x[0]==x[1], z) >>> s = sorted(f, key=lambda x:x[0]) >>> print(' The lucky number is :', [item[0] for item in s]) The lucky number is :[1, 2, 3]
If you've ever been written in one line by those 、 But it can achieve complex functions 、 The painful experience of code ravaging that looks like a heavenly book , that , Now you can also write the above code in one line , To ravage others .
>>> arr = [3,5,2,7,3,8,1,2,4,8,9,3] >>> print(' The lucky number is :', [item[0] for item in sorted(filter(lambda x:x[0]==x[1], zip(set(arr), map(arr.count, set(arr)))), key=lambda x:x[0])]) The lucky number is :[1, 2, 3]
Some people say , Why bother ? It's not easier to write like this 、 Is it easier to read ? Sure enough , I really want to !