1. 程式人生 > >python中的sorted、iteritems和operator.itemgetter

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]).