Спрашчае параўнанне дат

У мяне ёсць наступны код пітона, які робіць параўнанне даты для функцыі сартавання спісу (напрыклад, date_list.sort (CMP = ДКМП) . Я цікава, калі гэта магчыма, каб выдаліць /, калі тэставанне КССА і зрабіць яго Oneliner.

def dcmp(a, b):
    amm, add, ayy = [int(v) for v in a.split('/')]
    bmm, bdd, byy = [int(v) for v in b.split('/')]
    v = cmp(ayy, byy)
    if v != 0: return v
    v = cmp(amm, bmm)
    if v != 0: return v
    return cmp(add, bdd)

Абнаўленне: Дазвольце мне зрабіць гэта ясна, што мне цікава, гэта вы можаце выдаліць гэты блок кода з функцыі:

    v = cmp(ayy, byy)
    if v != 0: return v
    v = cmp(amm, bmm)
    if v != 0: return v
    return cmp(add, bdd)
1
Таму што яны счытваюцца з файла і паглядзець, як '10/12/2011 'і выкарыстоўваецца ў якасці Dict ключоў.
дададзена аўтар koblas, крыніца
Чаму аргументы радкі, якія пачынаюцца з? Python мае дата тып .
дададзена аўтар NullUserException, крыніца
Вы можаце выкарыстоўваць дата аб'екты ў якасці ключоў, а таксама.
дададзена аўтар NullUserException, крыніца
Я да гэтага часу думаю, што NullUserException мае кропку. Вы можаце лёгка ператварыць гэтыя радкі ў аб'екты даты і часу, выкарыстоўваючы strptime . Гэта дазволіць вам рабіць параўнанне, і вы можаце выкарыстоўваць іх у якасці ключоў Dict.
дададзена аўтар aganders3, крыніца

5 адказы

Вы можаце выкарыстоўваць ключ замест CMP . Гэта нашмат прасцей напісаць ключ функцыі, і можа быць зроблена ў адным радку.

date_list.sort(key = lambda s: datetime.strptime(s, '%m/%d/%Y'))

Вам таксама спатрэбіцца гэты імпарт:

from datetime import datetime
2
дададзена
Не кажучы ўжо пра тое, што з дапамогай кнопак ключ , верагодна, будзе больш эфектыўным.
дададзена аўтар PaulMcG, крыніца

Забудзьцеся пераўтварэнне даты, вы можаце зрабіць гэта ў выглядзе радкоў. Проста пераставіць іх у правільным парадку.

amm, add, ayy = a.split('/')
bmm, bdd, byy = b.split('/')
return cmp(ayy+amm+add, byy+bmm+bdd)

Я аддаю перавагу выкарыстоўваць ISO фармат даты , які ставіць рэчы ў правільным парадку для параўнання: YYYY-MM-DD . Яна таксама мае тое перавага, што не няслушна вытлумачаны на другім баку акіяна.

1
дададзена
@JohnMachin, справядлівая крытыка. Як я ўжо казаў, я аддаю перавагу выкарыстоўваць фарматы, дзе вядучыя нулі гарантавана. І дзякуй за тлумачэнні downvote, я цаню гэта нашмат лепш, чым ананімны выгляд.
дададзена аўтар Mark Ransom, крыніца
-1 У адрозненне ад кода OP, гэта будзе <б> збой , калі некалькі дзён ці месяцаў не маюць вядучых нулёў.
дададзена аўтар John Machin, крыніца
Так праўда пра іншы бок акіяна. Класічны збой: пакетнае заданне адхіляе каля 60% ад даты нараджэння і даты пачатку занятасці ў файле, прадастаўленых новай «другім баку» даччынай кампаніі. Rejects карпатліва «выпраўлена» і зноў ўвайшоў. Няма рэалізацыі (нашмат пазней), што яшчэ каля 37% былі б затыкнулі, але не выяўлена.
дададзена аўтар John Machin, крыніца

Фігурныя гэта тое, што я шукаў было замяніць толькі гэты код (<моцны> ігнараваць, што гэта даты )

v = cmp(ayy, byy)
if v != 0: return v
v = cmp(amm, bmm)
if v != 0: return v
return cmp(add, bdd)

Правільны адказ:

return cmp(ayy, byy) or cmp(amm, bmm) or cmp(add, bdd)

Які таксама можна запісаць у выглядзе:

return cmp((ayy,amm,add), (byy,bmm,bdd))
0
дададзена

Калі ўсе месяцы і дні з'яўляюцца нулямі і вашыя даты ў м/д/фармат Y, як «01.01.2001», вы маглі б напісаць:

def datekey(d):
    m, d, y = d.split('/')
    return (y, m, d)

datelist.sort(key=datekey)

Калі лічбы не заўсёды нулёў, можна адліваць кожны нумар да міжнар для параўнання:

def datekey(d):
    m, d, y = d.split('/')
    return (int(y), int(m), int(d))

datelist.sort(key=datekey)

Гэта <ет> спосаб хутчэй, чым пры выкарыстанні strptime калі ўсе даты вашага ў такім простым фармаце:

>>> import timeit
>>> print timeit.Timer("datelist.sort(key=datekey)",
...     setup="""\
... datelist = ['01/01/2001', '01/02/2001', '12/31/1999']
... def datekey(d):
...     m, d, y = d.split('/')
...     return (y, m, d)
... """).timeit()
3.3154168129

>>> print timeit.Timer("datelist.sort(key=datekey)",
...     setup="""\
... datelist = ['01/01/2001', '01/02/2001', '12/31/1999']
... def datekey(d):
...     m, d, y = d.split('/')
...     return (int(y), int(m), int(d))
... """).timeit()
11.1701700687

>>> print timeit.Timer("datelist.sort(key = lambda s: datetime.datetime.strptime(s, '%m/%d/%Y'))",
...     setup="""\
... datelist = ['01/01/2001', '01/02/2001', '12/31/1999']
... import datetime
... """).timeit()
59.2817358971

strptime is hugely powerful, very important to know, and very slow in this use case.

0
дададзена
-1 Бенчмаркі некарэктнага кода бескарысныя. <Код> datekey ('12/31/1 999 ') вырабляе [1999 31, 12] збой
дададзена аўтар John Machin, крыніца
Оо, падла. Рэд. Няма сэнсу ў тым, рыўком аб FAIL, хоць.
дададзена аўтар Kirk Strauser, крыніца

Гэта, вядома, чысцей, каб пераўтварыць гэтыя значэння фактычных дат (хоць, магчыма, больш павольна - you'd павінны бенчмарка яго, калі хуткасць з'яўляецца тое, што важна):

def dcmp(a, b):
    from datetime.datetime import strptime
    return strptime(a,'%m/%d/%Y') > strptime(b,'%m/%d/%Y')
0
дададзена