2011-02-02 69 views
3

我已經寫在Python 2.6以下代碼中,與具有Task類的可選due_date更改比較函數使用鍵進行排序

class Task(models.Model): 
    due_date = models.DateField(null = True, blank = True) 

    @staticmethod 
    def compare_by_due_date(t1, t2): 
     return due_date_cmp(t1.due_date, t2.due_date) 

def due_date_cmp(t1, t2): 
    if t1 is None and t2 is None: 
     return 0; 
    if t1 is None: 
     return 1 
    if t2 is None: 
     return -1 
    return (t1 - t2).days 

爲什麼提取的比較函數的類之外的原因是我希望能夠測試它,而無需構建Task實例。我用compare_by_due_date下面的代碼通過增加到期日定購任務,與不具有到期日在列表的最後任務:

tasks = Task.objects.all() 
tasks.sort(Task.compare_by_due_date) 

我從this answer on Code Review明白,我應該能夠使用keys instead of comparison function?你能告訴我如何?

+2

傳統上使用'is'而不是'=='。 – 2011-02-02 20:12:32

+0

謝謝!我編輯了這個問題。 – 2011-02-02 20:40:53

回答

4

你無法比較所有不同類型的對象(如datetime.date爲無),即使2.X並允許比3.x的不同類型之間更多的比較,所以due_dates的直接比較將不起作用。

def due_date_key(t): 
    return (t.due_date is None, t.due_date) 

tasks.sort(key=due_date_key) 

這是通過鏈接通過記錄進行比較,所以以後如果早期項目是相等的項目,纔會考慮。

2

看起來像due_date_cmp對由datetime.dateNone對象組成的列表進行排序,將None放在列表的末尾。

舊的方式(使用CMP):

你可以使用它None對象轉換爲最大可能datetime.date對象的關鍵做同樣的

import datetime as dt 

def due_date_cmp(t1, t2): 
    if t1 == None and t2 == None: 
     return 0; 
    if t1 == None: 
     return 1 
    if t2 == None: 
     return -1 
    return (t1 - t2).days 


dates=[dt.date(2000,1,1),None,dt.date(1999,1,1),None,dt.date(2002,1,1)] 
dates.sort(cmp=due_date_cmp) 
print(dates) 
# [datetime.date(1999, 1, 1), datetime.date(2000, 1, 1), datetime.date(2002, 1, 1), None, None] 

新的方式(使用鍵) :

def due_date_key(t): 
    if t is None: 
     return dt.date(dt.MAXYEAR,12,31) 
    else: 
     return t 

dates=[dt.date(2000,1,1),None,dt.date(1999,1,1),None,dt.date(2002,1,1)] 
dates.sort(key=due_date_key) 
print(dates) 

# [datetime.date(1999, 1, 1), datetime.date(2000, 1, 1), datetime.date(2002, 1, 1), None, None] 

因此,你可以使用due_date_key在你的代碼是這樣的:

import operator 
class Task(models.Model): 
    @property 
    def due_date_key(self): 
     due_date=self.due_date 
     if due_date is None: 
      return dt.date(dt.MAXYEAR,12,31) 
     else: 
      return due_date 

tasks = Task.objects.all() 
tasks.sort(key=operator.attrgetter('due_date_key')) 
+0

+1,用'用最大可能的日期替換None',並顯示如何使用`operator.attrgetter`。 – 2011-02-02 21:02:55

相關問題