2014-12-05 2 views
1

누락 날짜가있는 날짜/시간 목록을 누락 날짜를 기반으로하는 목록으로 나누려면 어떻게합니까?Python은 누락 날짜를 기준으로 날짜 시간대를 분할합니다.

다음 예를 사용 :

date_list = [ 
     datetime.datetime(2012,1,1,0,0,0), 
     datetime.datetime(2012,1,2,0,0,0), 
     datetime.datetime(2012,1,4,0,0,0), 
     datetime.datetime(2012,1,7,0,0,0), 
     datetime.datetime(2012,1,8,0,0,0), 
     ] 

결과를 내가 여기 찾고 있어요 것은 내가 groupby를 사용하여 시도하지만 키에 사용할 것을 알아낼 수 없습니다

[[datetime.datetime(2012,1,1,0,0,0), datetime.datetime(2012,1,2,0,0,0)] 
[datetime.datetime(2012,1,4,0,0,0)], 
[datetime.datetime(2012,1,7,0,0,0), datetime.datetime(2012,1,8,0,0,0)]] 

입니다.

[list(g) for k, g in itertools.groupby(date_list, key=lambda d: d.day)]

+0

[itertools docs] (https://docs.python.org/2.6/library/itertools.html#examples)의 두 번째 예가 유용 할 것입니다. 반면에 당신이 슈퍼 공상에 관심이 없다면, [자신의 발전기를 쓰는] (http://stackoverflow.com/questions/21142231/group-consecutive-integers-and-tolerate-gaps-of-1/ 21142465 # 21142465) 매우 간단합니다. – roippi

답변

2

이 주어진 예를 들어 작동 ...

>>> import datetime 
>>> date_list = [ 
...   datetime.datetime(2012,1,1,0,0,0), 
...   datetime.datetime(2012,1,2,0,0,0), 
...   datetime.datetime(2012,1,4,0,0,0), 
...   datetime.datetime(2012,1,7,0,0,0), 
...   datetime.datetime(2012,1,8,0,0,0), 
...   ] 
>>> import itertools 
>>> [list(g) for k, g in itertools.groupby(enumerate(date_list), key=lambda (i, x): i-x.day)] 
[[(0, datetime.datetime(2012, 1, 1, 0, 0)), (1, datetime.datetime(2012, 1, 2, 0, 0))], [(2, datetime.datetime(2012, 1, 4, 0, 0))], [(3, datetime.datetime(2012, 1, 7, 0, 0)), (4, datetime.datetime(2012, 1, 8, 0, 0))]] 

인덱스를하지 않으려면이 더있을 수 있습니다 ...

>>> [[v for i, v in g] for k, g in itertools.groupby(enumerate(date_list), key=lambda (i, x): i-x.day)] 
[[datetime.datetime(2012, 1, 1, 0, 0), datetime.datetime(2012, 1, 2, 0, 0)], [datetime.datetime(2012, 1, 4, 0, 0)], [datetime.datetime(2012, 1, 7, 0, 0), datetime.datetime(2012, 1, 8, 0, 0)]] 
1

당신은 만들 수 연속 된 날짜가 없을 때 "전환"하는 키 :

그럼 당신은 그것을 좋아 사용할 수 있습니다

다음
>>> [list(g) for k, g in groupby(date_list, key = Switcher())] 
[[datetime.datetime(2012, 1, 1, 0, 0), datetime.datetime(2012, 1, 2, 0, 0)], 
[datetime.datetime(2012, 1, 4, 0, 0)], 
[datetime.datetime(2012, 1, 7, 0, 0), datetime.datetime(2012, 1, 8, 0, 0)]] 
+0

이 클래스의'__call__' 기능만을 사용한다면 왜 그 기능을 사용하지 않는 것이 좋을까요? 그냥'class switcher' 라인을 지우고 들여 쓰기를 옮기고 이름을'__call__'으로 바꾸고'zip (date_list [1 :], date_list)'에 스위치 케이스를 계산하면됩니다. 결과는 코드가 적고 혼동이 적은 코드입니다. – ely

+0

@ prpl.mnky.dshwshr 그 이유는 이전 요소/스위치 상태를 기억하기 위해 키 객체가 메모리 ('self.prev','self.switch')를 가져야하기 때문입니다. 함수는 stateless 일 것입니다. – elyase

+0

그렇기 때문에 내가 지퍼처럼 스위치 상태를 계산하는 대신 상태라고 생각하는 것입니다. 저는 여러분이이 방법으로 그것을 표현할 수 있는지 여부를 논하는 것이 아닙니다. 단지 클래스를 잘 사용하지 못한다는 것입니다. 또한 생성자로 만들거나 클로저를 사용하여 함수에 "상태"를 가질 수 있습니다. – ely

2

은 그것을 할 수있는 재미를위한 루프 도우미 함수입니다.

def date_segments(dates): 
    output = [] 
    cur_list = [dates[0]] 
    for dt_pair in zip(dates[1:], dates): 
     if (dt_pair[0] - dt_pair[1]).days > 1: 
      output.append(cur_list) 
      cur_list = [dt_pair[0]] 
     else: 
      cur_list.append(dt_pair[0]) 
    output.append(cur_list) 
    return output 

준다 :

In [28]: date_segments(date_list) 
Out[28]: 
[[datetime.datetime(2012, 1, 1, 0, 0), datetime.datetime(2012, 1, 2, 0, 0)], 
[datetime.datetime(2012, 1, 4, 0, 0)], 
[datetime.datetime(2012, 1, 7, 0, 0), datetime.datetime(2012, 1, 8, 0, 0)]] 

I 아래와 같이 other_way라는 도우미 함수로서 itertools.groupby 접근 정의하면이 틀림 작은 예 timeit 대한 다음

from itertools import groupby 
def other_way(date_list): 
    return [[v for i, v in g] for k, g in groupby(enumerate(date_list), 
                key=lambda (i, x): i-x.day)] 

이 for-를 도시 루프 접근 방식이 약간 더 빠름 :

In [31]: %timeit date_segments(date_list) 
100000 loops, best of 3: 3.2 µs per loop 

In [32]: %timeit other_way(date_list) 
100000 loops, best of 3: 3.72 µs per loop 

그리고 나는 for-loop 방식을 훨씬 더 Pythonic하고 읽기 쉽다고 생각한다.

관련 문제