Python 排序---sort與sorted學習
當我們從數據庫中獲取一寫數據後,一般對於列表的排序是經常會遇到的問題,今天總結一下python對於列表list排序的常用方法:
第一種:內建方法sort()
可以直接對列表進行排序
用法:
list.sort(func=None, key=None, reverse=False(or True))
- 對於reverse這個bool類型參數,當reverse=False時:為正向排序;當reverse=True時:為方向排序。默認為False。
- 執行完後會改變原來的list,如果你不需要原來的list,這種效率稍微高點
- 為了避免混亂,其會返回none
例如:
1 2 3 4 |
>>> list = [ 2 , 8 , 4 , 6 , 9 , 1 , 3 ]
>>> list .sort()
>>> list
[ 1 , 2 , 3 , 4 , 6 , 8 , 9 ]
|
第二種:內建函數sorted()
這個和第一種的差別之處在於:
- sorted()不會改變原來的list,而是會返回一個新的已經排序好的list
- list.sort()方法僅僅被list所定義,sorted()可用於任何一個可叠代對象
用法:
sorted(list)
- 該函數也含有reverse這個bool類型的參數,當reverse=False時:為正向排序(從小到大);當reverse=True時:為反向排序(從大到小)。當然默認為False。
- 執行完後會有返回一個新排序好的list
例如:
1 2 3 4 |
>>> list = [ 2 , 8 , 4 , 1 , 5 , 7 , 3 ]
>>> other = sorted ( list )
>>> other
[ 1 , 2 , 3 , 4 , 5 , 7 , 8 ]
|
擴展用法:
1.Key Function:
從Python2.4開始,list.sort() 和 sorted() 都增加了一個 ‘key’ 參數用來在進行比較之前指定每個列表元素上要調用的函數。
例如:
區分大小寫的字符串比較排序:
>>> sorted("This is a test string from Andrew".split(), key=str.lower)
[‘a‘, ‘Andrew‘, ‘from‘, ‘is‘, ‘string‘, ‘test‘, ‘This‘]
key應該是一個函數,其接收一個參數,並且返回一個用於排序依據的key。其執行效率很高,因為對於輸入記錄key function能夠準確的被調用。
對於復雜的對象,使用對象的下標作為key。
例如:
>>> student_tuples = [
... (‘john‘, ‘A‘, 15),
... (‘jane‘, ‘B‘, 12),
... (‘dave‘, ‘B‘, 10),
... ]
>>> sorted(student_tuples, key=lambda student: student[2]) # sort by age
[(‘dave‘, ‘B‘, 10), (‘jane‘, ‘B‘, 12), (‘john‘, ‘A‘, 15)]
使用對象的屬性進行操作:
例如:
>>> class Student:
... def __init__(self, name, grade, age):
... self.name = name
... self.grade = grade
... self.age = age
... def __repr__(self):
... return repr((self.name, self.grade, self.age))
>>>
>>> student_objects = [
... Student(‘john‘, ‘A‘, 15),
... Student(‘jane‘, ‘B‘, 12),
... Student(‘dave‘, ‘B‘, 10),
... ]
>>> sorted(student_objects, key=lambda student: student.age) # sort by age
[(‘dave‘, ‘B‘, 10), (‘jane‘, ‘B‘, 12), (‘john‘, ‘A‘, 15)]
前段時間遇到這種情況,那就是列表裏面每一個元素不止一個元素(比如:列表裏面,元素為元祖類型),我們除了想對第一個關鍵字排序之外,還想在第一次的基礎上面根據第二個關鍵字進行排序,正好是用到的這種方法:
簡化出一個例子:
我們想先排序列表list中元素的第一個關鍵字,然後在第一個元素的基礎上排序按第二個關鍵字進行排序,看結果:
1 2 3 |
>>> list = [( ‘d‘ , 3 ),( ‘a‘ , 5 ),( ‘d‘ , 1 ),( ‘c‘ , 2 ),( ‘d‘ , 2 )]
>>> print sorted ( list , key = lambda x:(x[ 0 ],x[ 1 ]))
[( ‘a‘ , 5 ), ( ‘c‘ , 2 ), ( ‘d‘ , 1 ), ( ‘d‘ , 2 ), ( ‘d‘ , 3 )]
|
2.Operator Module Functions
這個操作模塊有:
operator.itemgetter() ----- 通過下標
operator.attrgetter() ----- 通過參數
operator.methodcaller() -----python 2.5 被引入,下文詳細介紹
使用這幾個函數,對於上面 Key Function 的例子處理起來將會更加的簡便和快速
先一塊介紹 operator.itemgetter() 和 operator.attrgetter() 這倆個,會更加容易理解:
例如:
>>> from operator import itemgetter, attrgetter
>>>
>>> sorted(student_tuples, key=itemgetter(2))
[(‘dave‘, ‘B‘, 10), (‘jane‘, ‘B‘, 12), (‘john‘, ‘A‘, 15)]
>>>
>>> sorted(student_objects, key=attrgetter(‘age‘))
[(‘dave‘, ‘B‘, 10), (‘jane‘, ‘B‘, 12), (‘john‘, ‘A‘, 15)]
這個操作模塊也允許多層次的進行排序,例如可以先排序 “成績grand” 再排序 “年齡age”
例如:
>>> sorted(student_tuples, key=itemgetter(1,2))
[(‘john‘, ‘A‘, 15), (‘dave‘, ‘B‘, 10), (‘jane‘, ‘B‘, 12)]
>>>
>>> sorted(student_objects, key=attrgetter(‘grade‘, ‘age‘))
[(‘john‘, ‘A‘, 15), (‘dave‘, ‘B‘, 10), (‘jane‘, ‘B‘, 12)]
現在回過頭來發現,上面在前幾天遇到的問題,可以用這個operator.itemgetter進行解決:
>>> list = [(‘d‘,3),(‘a‘,5),(‘d‘,1),(‘c‘,2),(‘d‘,2)]
>>> from operator import itemgetter
>>> sorted(list, key=itemgetter(0,1))
[(‘a‘, 5), (‘c‘, 2), (‘d‘, 1), (‘d‘, 2), (‘d‘, 3)]
但是還是推薦 1.key function 中的方法,因為為了這一個排序而引入一個庫文件,相對來說得不償失。
下面介紹operator.methodcaller() 函數:
這個函數是對某個對象的使用固定參數進行排序,例如:str.count() 函數可以計算每個字符串對象中含有某個參數的個數,那運用這個函數我就可以通過 str.count() 計算出某個字符的個數從而來確定排序的優先級:
>>> from operator import methodcaller
>>> messages = [‘critical!!!‘, ‘hurry!‘, ‘standby‘, ‘immediate!!‘]
>>> sorted(messages, key=methodcaller(‘count‘, ‘!‘))
[‘standby‘, ‘hurry!‘, ‘immediate!!‘, ‘critical!!!‘]
3.註意事項:
排序的穩定性:
從python2.2版本開始,排序是保障穩定性的,意思就是說,當復雜的排序中,對象有相同的key的時候,會保持原有的順序不變:
例如:
>>> data = [(‘red‘, 1), (‘blue‘, 1), (‘red‘, 2), (‘blue‘, 2)]
>>> sorted(data, key=itemgetter(0))
[(‘blue‘, 1), (‘blue‘, 2), (‘red‘, 1), (‘red‘, 2)]
可以看到,(‘blue‘,1) 和 (‘blue’,2) 的順序還是維持原來那樣不改變。
復雜排序:
這個排序的屬性可以讓你在一系列的步驟中構建復雜的排序操作。例如上面的例子,排序中,我想先通過 “成績grand” 進行降序操作,然後再通過“年齡age” 進行升序操作,首先先通過 “年齡age” 排序,然後再通過 “成績grand” 排序:
>>> s = sorted(student_objects, key=attrgetter(‘age‘)) # sort on secondary key
>>> sorted(s, key=attrgetter(‘grade‘), reverse=True) # now sort on primary key, descending
[(‘dave‘, ‘B‘, 10), (‘jane‘, ‘B‘, 12), (‘john‘, ‘A‘, 15)]
4.新增的問題:
今天遇到了這麽一個問題,就是遇到一個字符串的處理問題,比如說 f10 得排在 f2 的後面。找到了這麽一種方法,供參考:
參考地址:http://blog.csdn.net/houyj1986/article/details/22966799
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#encoding=utf-8
print ‘中國‘
#根據字符串中的數字排序,如f10應該在f2後面
import re
re_digits = re. compile (r ‘(\d+)‘ )
def emb_numbers(s):
pieces = re_digits.split(s)
pieces[ 1 :: 2 ] = map ( int ,pieces[ 1 :: 2 ])
return pieces
def sort_strings_with_emb_numbers(alist):
aux = [(emb_numbers(s),s) for s in alist]
aux.sort()
return [s for __,s in aux]
def sort_strings_with_emb_numbers2(alist):
return sorted (alist, key = emb_numbers)
filelist = ‘file10.txt file2.txt file1.txt‘ .split()
print filelist
print ‘--DSU排序‘
print sort_strings_with_emb_numbers(filelist)
print ‘--內置DSU排序‘
print sort_strings_with_emb_numbers2(filelist)
|
打印結果如下:
1 2 3 4 5 6 |
中國
[ ‘file10.txt‘ , ‘file2.txt‘ , ‘file1.txt‘ ]
- - DSU排序
[ ‘file1.txt‘ , ‘file2.txt‘ , ‘file10.txt‘ ]
- - 內置DSU排序
[ ‘file1.txt‘ , ‘file2.txt‘ , ‘file10.txt‘ ]
|
Python 排序---sort與sorted學習