2016-01-20 66 views
3

我有一個dict()調用twitter_users其中包含TwitterUser對象作爲值。我希望這些對象按字段mentioned排序。但是,使用sorted()不能像我所期望的那樣工作。我提供lambda功能,應該確定用戶a或用戶b是否更經常提及。爲什麼我的列表沒有按預期排序?

srt = sorted(twitter_users.values(), 
     cmp=(lambda a,b: 
       True if a.mentioned > b.mentioned else False)) 

for s in srt: 
    print s.mentioned 

不幸的是,這不起作用,名單srt沒有以任何方式排序。

我該如何做這項工作?

+3

,這是更好的寫作'排序(LST,關鍵= lambda x:x. mentioned)' – shx2

+0

'提到'的類型是什麼? – Thomas

+0

@Thomas整數 – displayname

回答

10

cmp一個函數應返回的整數,當0相等,1或當a應該來b-1或更低,如果他們應該來以相反的順序後更高。

您改爲返回FalseTrue。由於Python布爾類型是int的子類,因此在解釋爲整數時,這些對象的值爲01。你永遠不會返回-1,所以你混淆了排序算法;你告訴它,ab的順序要麼總是'等於',要麼總是應該在b之前應該有a。但排序算法有時要求ab交換,在這種情況下,您給它提供了衝突信息!

請注意,您的表情比較冗長; True if a.mentioned > b.mentioned else False可以簡化爲a.mentioned > b.mentioned; >運營商已經生產了TrueFalse。使用簡單的整數,你可以看到,這是不會產生預期的結果:

>>> sorted([4, 2, 5, 3, 8], cmp=lambda a, b: a > b) 
[4, 2, 5, 3, 8] 

而實際返回-10,或1做工作:

>>> sorted([4, 2, 5, 3, 8], cmp=lambda a, b: 1 if a > b else 0 if a == b else -1) 
[2, 3, 4, 5, 8] 

或代替這種冗長的表達方式,只需使用內置的cmp() function;你的情況下,你使用的是這樣的:

srt = sorted(twitter_users.values(), cmp=lambda a, b: cmp(a.mentioned, b.mentioned)) 

但你真的不應該使用cmp在所有;有一個更簡單(更高效)的選擇。只需使用key函數來代替,它簡單的返回mentioned屬性:

srt = sorted(twitter_users.values(), key=lambda v: v.mentioned) 

key功能產生由實際的排序發生值;此功能用於生成Schwartzian transform。這種變換更高效,因爲它只被稱爲O(n)次,而函數O(n log n)次被稱爲O(n log n)次。

因爲你只訪問一個屬性,而不是lambda,你可以用一個operator.attrgetter() object做屬性獲取爲您:在任何情況下

from operator import attrgetter 

srt = sorted(twitter_users.values(), key=attrgetter('mentioned')) 
+0

這是行得通,謝謝! :) – displayname

相關問題