2010-07-07 16 views
5

Tengo una lista ordenada (es decir, ordenada) que contiene fechas ordenadas (como objetos datetime) en orden ascendente.Creando una lista de meses iterando entre dos fechas en una lista (Python)

Quiero escribir una función que itera a través de esta lista y genera otra lista de las primeras fechas disponibles para cada mes.

Por ejemplo, supongamos que mi lista ordenada contiene los siguientes datos:

A = [ 
'2001/01/01', 
'2001/01/03', 
'2001/01/05', 
'2001/02/04', 
'2001/02/05', 
'2001/03/01', 
'2001/03/02', 
'2001/04/10', 
'2001/04/11', 
'2001/04/15', 
'2001/05/07', 
'2001/05/12', 
'2001/07/01', 
'2001/07/10', 
'2002/03/01', 
'2002/04/01', 
] 

La lista devuelta sería

B = [ 
'2001/01/01', 
'2001/02/04', 
'2001/03/01', 
'2001/04/10', 
'2001/05/07', 
'2001/07/01', 
'2002/03/01', 
'2002/04/01', 
] 

La lógica que propongo sería algo como esto:

def extract_month_first_dates(input_list, start_date, end_date): 
    #note: start_date and end_date DEFINITELY exist in the passed in list 
    prev_dates, output = [],[] # <- is this even legal? 
    for (curr_date in input_list): 
     if ((curr_date < start_date) or (curr_date > end_date)): 
      continue 

     curr_month = curr_date.date.month 
     curr_year = curr_date.date.year 
     date_key = "{0}-{1}".format(curr_year, curr_month) 
     if (date_key in prev_dates): 
      continue 
     else: 
      output.append(curr_date) 
      prev_dates.append(date_key) 

    return output 

¿Algún comentario, sugerencia? - ¿Se puede mejorar esto para ser más 'Ptónico'?

+0

@ "# <- ¿esto es legal?": sí, se llama * asignación múltiple * – miku

+0

'para (curr_date en input_list)' es un error de sintaxis; no hay paréntesis aquí en Python. – Philipp

+0

Su ejemplo de datos consiste en cadenas, en su texto usted escribe que tiene objetos datetime. Quizás debas aclarar que algunas de las soluciones son específicas para cadenas, tendrás que reescribirlas ligeramente para objetos datetime. –

Respuesta

7
>>> import itertools 
>>> [min(j) for i, j in itertools.groupby(A, key=lambda x: x[:7])] 
['2001/01/01', '2001/02/04', '2001/03/01', '2001/04/10', '2001/05/07', '2001/07/01', '2002/03/01', '2002/04/01'] 
+2

¡agradable! - PERO, no lo entiendo. Cuidado para explicar qué está pasando, para que los simples mortales podamos entender;)? – morpheous

+1

Consulte la documentación de itertools.groupby() (http://docs.python.org/library/itertools.html#itertools.groupby). Y asegúrese de que la lista esté ordenada si usa esta solución, de lo contrario no funcionará. –

+0

@morpheous: agrupo las fechas en función del mes (las primeras 7 cadenas de caracteres del día), luego selecciono el valor mínimo del grupo, que forma un elemento de la lista de salida. – SilentGhost

1

listas buscando es un (n) operación O. Creo que se puede simplemente comprobar si la clave es nueva:

def extract_month_first_dates(input_list): 
    output = [] 
    last_key = None 
    for curr_date in input_list: 
     date_key = curr_date.date.month, curr_date.date.year # no string key required 
     if date_key != last_key: 
      output.append(curr_date) 
      last_key = date_key 
    return output 
+0

@phillip: +1 para la sugerencia útil !. Por cierto, estás asignando variables a uno, ¿qué está pasando ?. ¿El operador de coma está sobrecargado para enteros en Python? – morpheous

+0

@morpheous: Comma es un operador estándar en Python. El valor de la expresión 'x, y' es una tupla que consiste en' x' y 'y'. En su ejemplo original, '[], []' también es solo una tupla que consta de dos listas vacías. – Philipp

0

Aquí es una solución simple en classic python es decir, no hay itertools;) y explica por sí mismo

visited = {} 
B = [] 
for a in A: 
    month = a[:7] 
    if month not in visited: 
     B.append(a) 
    visited[month] = 1 

print B 

salida de la señal:

['2001/01/01', '2001/02/04', '2001/03/01', '2001/04/10', '2001/05/07', '2001/07/01', '2002/03/01', '2002/04/01'] 
Cuestiones relacionadas