python中的sorted、iteritems和operator.itemgetter
最近在看《機器學習實戰》,在學到第三章遞迴構建決策樹時看到以下程式碼:
def majorityCnt(classList):
classCount = {}
for vote in classList:
if vote not in classCount.keys():classCount[vote] = 0
classCount[vote] += 1
sortedClassCount = sorted(classCount.iteritems(),\
key=operator.itemgetter(1 ),reverse=True)
return sortedClassCount[0][0]
上述程式碼使用分類名稱的列表,然後建立鍵值為classList中唯一值的資料字典,字典物件儲存了classList中每個類標籤出現的頻率,最後利用operator操作鍵值排序字典,並返回出現次數最多的分類名稱。
第六、七行沒看太懂,於是查閱了相關知識點。
一、iteritems()
字典的items()方法和iteritems()方法,是python字典的內建函式,分別會返回Python列表和迭代器。
python字典的items方法作用:是可以將字典中的所有項,以列表方式返回。如果對字典項的概念不理解,可以檢視Python對映型別字典基礎知識一文。因為字典是無序的,所以用items方法返回字典的所有項,也是沒有順序的。
python字典的iteritems方法作用:與items方法相比作用大致相同,只是它的返回值不是列表,而是一個迭代器。
字典items()操作方法:
>>> x = {'title':'python web site','url':'www.iplaypy.com'}
>>> x.items()
[('url', 'www.iplaypy.com'), ('title', 'python web site')]
從結果中可以看到,items()方法是將字典中的每個項分別做為元組,新增到一個列表中,形成了一個新的列表容器。如果有需要也可以將返回的結果賦值給新變數,這個新的變數就會是一個列表資料型別。
>>> a=x.items()
>>> a
[('url', 'www.iplaypy.com'), ('title', 'python web site')]
>>> type(a)
<type 'list'>
dict iteritems()操作方法:
>>> f = x.iteritems()
>>> f
<dictionary-itemiterator object at 0xb74d5e3c>
>>> type(f)
<type 'dictionary-itemiterator'> #字典項的迭代器
>>> list(f)
[('url', 'www.iplaypy.com'), ('title', 'python web site')]
字典.iteritems()方法在需要迭代結果的時候使用最適合,而且它的工作效率非常的高。
二、operator.itemgetter函式
operator模組提供的itemgetter函式用於獲取物件的哪些維的資料,引數為一些序號(即需要獲取的資料在物件中的序號),下面看例子。
a = [1,2,3]
b=operator.itemgetter(1) //定義函式b,獲取物件的第1個域的值>
print b(a) //2
b=operator.itemgetter(1,0) //定義函式b,獲取物件的第1個域和第0個的值
print b(a) //(2, 1)
要注意,operator.itemgetter函式獲取的不是值,而是定義了一個函式,通過該函式作用到物件上才能獲取值。
用 operator 函式進行多級排序
students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10),]
>>> sorted(students, key=itemgetter(1,2)) # sort by grade then by age
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
## 對字典排序
>>> d = {'data1':3, 'data2':1, 'data3':2, 'data4':4}
>>> sorted(d.iteritems(), key=itemgetter(1), reverse=True)
[('data4', 4), ('data1', 3), ('data3', 2), ('data2', 1)]
三、sorted和sort
sort() 是Python列表的一個內建的排序方法,list.sort() 方法排序時直接修改原列表,返回None;
sorted() 是Python內建的一個排序函式,它會從一個迭代器返回一個排好序的新列表。
相比於 sort(),sorted() 使用的範圍更為廣泛,但是如果不需要保留原列表,sort更有效一點。另外,sort() 只是列表的一個方法,只適用於列表,而sorted() 函式接受一切迭代器,返回新列表。
兩者的函式形式分別如下(Python3.5.2):
sorted(iterable[, key][, reverse])
list.sort(*, key=None, reverse=None)
這兩個方法有以下 2 個共同的引數:
key 是帶一個引數的函式,返回一個值用來排序,預設為 None。這個函式只調用一次,所以fast。
reverse 表示排序結果是否反轉
看例子:
>>> a = (1,2,4,2,3) # a 是元組,故不能用sort() 排序
>>> a.sort()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'sort'
>>> sorted(a) # sorted() 可以為元組排序,返回一個新有序列表
[1, 2, 2, 3, 4]
>>> a=['1',1,'a',3,7,'n']
>>> sorted(a)
[1, 3, 7, '1', 'a', 'n']
>>> a # sorted() 不改變原列表
['1', 1, 'a', 3, 7, 'n']
>>> print a.sort()
None
>>> a # a.sort()直接修改原列表
[1, 3, 7, '1', 'a', 'n']
因此如果實際應用過程中需要保留原有列表,使用 sorted() 函式較為適合,否則可以選 擇 sort() 函式,因為 sort() 函式不需要複製原有列表,消耗的記憶體較少,效率也較高。
sorted() 函式功能非常強大,它可以方便地針對不同的資料結構進行排序,從而滿足不同需求。例子如下:
對字典進行排序
>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'}) # 根據字典鍵排序
[1, 2, 3, 4, 5]
>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'}.values()) # 根據字典值排序
['A', 'B', 'B', 'D', 'E']
對多維列表排序
>>> student_tuples = [('john', 'A', 15),('jane', 'B', 12),('dave', 'B', 10)]
>>> sorted(student_tuples, key = lambda student: student[0]) # 對姓名排序
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(student_tuples, key = lambda student: student[2]) # 年齡排序
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
呼叫operator模組中的 itemgetter() 可以實現根據多個引數排序:
>>> sorted(student_tuples, key = itemgetter(2)) # 根據年齡排序
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(student_tuples, key = itemgetter(1, 2)) # 根據成績和年齡排序
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
>>> sorted(student_tuples, key = itemgetter(1, 2), reverse=True) # 反轉排序結果
[('jane', 'B', 12), ('dave', 'B', 10), ('john', 'A', 15)]
ps: itemgetter 返回一個函式,實現取元素的功能。比如
f = itemgetter(2),呼叫 f(r) 返回 r[2];
f = itemgetter(2, 5, 3),呼叫 f(r) 返回元組 (r[2], r[5], r[3]).