2015-06-22 36 views
1

我想根據日期對字典列表進行排序。如何忽略無效輸入或在排序函數中添加除代碼之外的嘗試?

下面的代碼是工作得很好,我的數據格式是修復IE DD/MM/YYYY

代碼:

[{'date': '10/10/2015'}, 
{'date': '11/10/2015'}, 
{'date': '01/01/2015'}, 
{'date': '10/12/2014'}, 
{'date': '01/01/2014'}, 
{'date': '2015'}] 

In [20]: a.pop() 
Out[20]: {'date': '2015'} 

In [21]: sorted(a, key=lambda x: datetime.datetime.strptime(x['date'], "%d/%m/%Y"), reverse=False) 
Out[21]: 
[{'date': '01/01/2014'}, 
{'date': '10/12/2014'}, 
{'date': '01/01/2015'}, 
{'date': '10/10/2015'}, 
{'date': '11/10/2015'}] 

但我也有時間值不能與DD/MM搭配/ yyyy格式。 獲取以下情況除外:

代碼2:

In [22]: a.append({"date":"2015"}) 

In [23]: sorted(a, key=lambda x: datetime.datetime.strptime(x['date'], "%d/%m/%Y"), reverse=False) 
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-23-abd07eed54eb> in <module>() 
----> 1 sorted(a, key=lambda x: datetime.datetime.strptime(x['date'], "%d/%m/%Y"), reverse=False) 

<ipython-input-23-abd07eed54eb> in <lambda>(x) 
----> 1 sorted(a, key=lambda x: datetime.datetime.strptime(x['date'], "%d/%m/%Y"), reverse=False) 

/usr/lib/python2.7/_strptime.py in _strptime(data_string, format) 
    323  if not found: 
    324   raise ValueError("time data %r does not match format %r" % 
--> 325       (data_string, format)) 
    326  if len(data_string) != found.end(): 
    327   raise ValueError("unconverted data remains: %s" % 

ValueError: time data '2015' does not match format '%d/%m/%Y' 

In [24]: 

如何sorted函數處理這種投入?

回答

2

我們的數據:

In [51]: a = [{'date': '10/10/2015'}, 
    ....: {'date': '11/10/2015'}, 
    ....: {'date': '01/01/2015'}, 
    ....: {'date': '10/12/2014'}, 
    ....: {'date': '01/01/2014'}, 
    ....: {'date': '2015'}] 

首先從a

In [52]: a = [i for i in a if len(i['date'])>9] 

其次刪除錯誤的日期:

In [53]: sorted(a, key=lambda x: datetime.datetime.strptime(x['date'], "%d/%m/%Y"), reverse=False) 
Out[53]: 
[{'date': '01/01/2014'}, 
{'date': '10/12/2014'}, 
{'date': '01/01/2015'}, 
{'date': '10/10/2015'}, 
{'date': '11/10/2015'}] 

你可以把它寫在一行:

sorted([i for i in a if len(i['date'])>9], key=lambda x: datetime.datetime.strptime(x['date'], "%d/%m/%Y"), reverse=False) 
+0

謝謝你,但是'語法錯誤:無效syntax' –

+0

@VivekSable看到更新 –

+0

確定。 Upvoted。我會檢查.. –

2

一個選項是在關鍵函數來處理異常:

def custom_sort(x): 
    try: 
     return datetime.datetime.strptime(x['date'], "%d/%m/%Y") 
    except ValueError: 
     # do something else if the date format is different 
    except KeyError: 
     # do something else if there is no 'date' key in x 
     # ... 

sorted(a, key=custom_sort) 

,或者您可以使用if-else結構將日期時間函數之前的數據,以正確的格式轉換...


編輯:這裏有2位更實用的選項:

a = [{'date': '05/06/2017'}, {'ff': 2016}, {'date': 2015}, {'date': '05/06/2014'}, 'ff'] 

def sort_by_converting_to_strings(x): 
    try: 
     return str(datetime.datetime.strptime(x['date'], "%d/%m/%Y")) 
    except (KeyError, ValueError, TypeError): 
     try: 
      return str(x['date']) 
     except (KeyError, TypeError): 
       return str(x) 
print sorted(a, key=sort_by_converting_to_strings) 
# [{'date': '05/06/2014'}, {'date': 2015}, {'date': '05/06/2017'}, 'ff', {'ff': 2016}] 


def validate(x): 
    try: 
     datetime.datetime.strptime(x['date'], "%d/%m/%Y") 
     return True 
    except Exception: 
     return False 
print sorted([i for i in a if validate(i)]) 
# [{'date': '05/06/2014'}, {'date': '05/06/2017'}] 

當然,你可以結合的方法,以獲得適合您的特定使用案例的解決方案......

+0

向上投票+1是的,我還創建了函數,它只返回有效的日期格式到排序函數。即在輸入列表上預處理。在排序函數中是否有任何方法來忽略這些輸入項目。 –

+0

'custom_sort'在執行'sorted'函數期間以與匿名lambda相同的方式被應用,它不會預處理輸入列表,也就是說它不會更新任何值...或者您需要什麼樣的plz ? – Aprillion

+0

「忽略」是什麼意思?您可以從輸出列表中刪除這些項目,將它們放到開頭,結束或任意與其他項目混合 - 但是如果您刪除它們,則排序列表的長度將不會與原始列表的長度相同。 – Aprillion

相關問題