Python中對複雜資料結構排序(類似C中結構體資料結構),python資料結構
Python中排序主要有兩個函數:sorted和列表成員函數sort,兩者除了調用方式有些區別外,最顯著的區別是sorted會建立一個排序好的列表並返回,而sort是修改原列表並排好序。sorted的原型是:
sorted(iterable, cmp=None, key=None, reverse=False)
sort的原型是:
list.sort(cmp=None, key=None, reverse=False)
其中cmp和key都是函數引用,即可以傳入函數名。這兩個函數都是對list裡的成員進行運算。reverse是指是否逆序。
在c中經常會出現結構體或鏈表之類的資料結構,而這在Python中也是可以處理的。
如資料結構是這樣的:
學號 分數1 分數210000007 90 78
那麼可以用一個列表儲存學生的資訊,即
info = ['10000007', '90', '78']
如果是簡單的按某一分數進行排序,如按分數2排序,則可以這樣:
如果輸入的資料是:
14 #學生總數10000001 64 90 #具體資訊10000002 90 6010000011 85 8010000003 85 8010000004 80 8510000005 82 7710000006 83 7610000007 90 7810000008 75 7910000009 59 9010000010 88 4510000012 80 10010000013 90 9910000014 66 60
代碼:
#!/usr/bin/pythondef getKey( x ): return int(x[2])num = input()list = [] for i in range(num): info = raw_input().split() list.append(info)list.sort( key=getKey )for i in list: print i[0], i[1], i[2]
輸出為:
10000010 88 4510000002 90 6010000014 66 6010000006 83 7610000005 82 7710000007 90 7810000008 75 7910000011 85 8010000003 85 8010000004 80 8510000001 64 9010000009 59 9010000013 90 9910000012 80 100
代碼量相較於c是精簡很多,這歸功與Python強大的功能(但在大量資料處理時,時間效率和空間效率一般都比c低,但開發效率很高)。
這是通過傳遞key來排序,也可以通過傳遞cmp函數來排序。再看一個複雜的例子:
題目描述:
輸入第1行給出3個正整數,分別為:N(<=105),即考生總數;L(>=60),為錄取最低分數線,即德分和才分均不低於L的考生才有資格被考慮錄取;H(<100),為優先錄取線——德分和才分均不低於此線的被定義為“才德全盡”,此類考生按德才總分從高到低排序;才分不到但德分到線的一類考生屬於“德勝才”,也按總分排序,但排在第一類考生之後;德才分均低於H,但是德分不低於才分的考生屬於“才德兼亡”但尚有“德勝才”者,按總分排序,但排在第二類考生之後;其他達到最低線L的考生也按總分排序,但排在第三類考生之後。
隨後N行,每行給出一位考生的資訊,包括:准考證號、德分、才分,其中准考證號為8位整數,德才分為區間[0, 100]內的整數。數字間以空格分隔。
輸出格式:
輸出第1行首先給出達到最低分數線的考生人數M,隨後M行,每行按照輸入格式輸出一位考生的資訊,考生按輸入中說明的規則從高到低排序。當某類考生中有多人總分相同時,按其德分降序排列;若德分也並列,則按准考證號的升序輸出。
原題見:http://pat.zju.edu.cn/contests/pat-b-practise/1015
代碼:
#!/usr/bin/pythonfrom sys import exitdef myCmp( a, b ): valuea = 2 * int(a[1]) + int(a[2]) valueb = 2 * int(b[1]) + int(b[2]) if valuea > valueb: return -1 elif valuea == valueb: if a[0] < b[0]: return -1 else: return 1 else: return 1rawIn = raw_input().split()num = int(rawIn[0])jige = int(rawIn[1])prio = int(rawIn[2])firstClass = []secondClass = []thirdClass = []forthClass = []for i in range(num): rawIn = raw_input().split() if int(rawIn[1]) >= prio and int(rawIn[2]) >= prio: firstClass.append(rawIn) elif int(rawIn[1]) >= prio and jige <= int(rawIn[2]) <= prio: secondClass.append(rawIn) elif int(rawIn[1]) >= jige and int(rawIn[2]) >= jige and int(rawIn[1]) >= int(rawIn[2]): thirdClass.append(rawIn) elif int(rawIn[1]) >= jige and int(rawIn[2]) >= jige: forthClass.append(rawIn) else: passfirstClass.sort(cmp=myCmp)secondClass.sort(cmp=myCmp)thirdClass.sort(cmp=myCmp)forthClass.sort(cmp=myCmp) print len(firstClass) + len(secondClass) + len(thirdClass) + len(forthClass)for i in [firstClass, secondClass, thirdClass, forthClass]: for j in i: print j[0], j[1], j[2]exit(0)
輸入:
14 60 8010000001 64 9010000002 90 6010000011 85 8010000003 85 8010000004 80 8510000005 82 7710000006 83 7610000007 90 7810000008 75 7910000009 59 9010000010 88 4510000012 80 10010000013 90 9910000014 66 60
輸出:
1210000013 90 9910000012 80 10010000003 85 8010000011 85 8010000004 80 8510000007 90 7810000006 83 7610000005 82 7710000002 90 6010000014 66 6010000008 75 7910000001 64 90
不過這份代碼在提交OJ時是存在幾個case逾時的,這也是Python存在的一個問題(不知道有沒有更高效的Python方法)。這裡為什麼不用key呢,是因為該題的比較過程通過key很難完全體現出來,所以用cmp,這也說明cmp的適用性更廣。但是由於key只是涉及單個list元素的計算,而cmp涉及兩個list元素的計算,所以key更高效。