2013-05-28 4 views
0

У меня есть список списка, который идет следующим образом:Получить элементы между двумя датами из списка

A = [['05-22-2013', '0.5553', '0.887', '0.14'], 
    ['05-22-2013', '0.3442', '0.345', '0.0'], 
    ['05-22-2013', '0.3', '0.7', '0.4'], 
    ['05-23-2013', '0.53', '0.87', '0.4'], 
    ['05-23-2013', '0.9', '0.8', '0.1'], 
    ['05-23-2013', '0.0', '0.799', '0.214'], 
    ['05-24-2013', '0.053', '0.7', '0.1422'], 
    ['05-25-2013', '0.5', '0.110', '0.200'], 
    ['05-25-2013', '0.311', '0.799', '0.426'], 
    ['05-25-2013', '0.311', '0.091', '0.41']] 

Я хочу, чтобы выбрать все элементы между датами в '05 -22-2013' до '05 - 24-2013. Я пытаюсь вручную получить все элементы, соответствующие каждой дате в массиве, и добавить их в единый список. Как на одну дату:

date_1 = [] 

for u in A: 
    if '05-22-2013' in u: 
     date_1.append(u) 

Так, в частности, о том, что является лучшим возможным способом, чтобы получить все элементы в пределах заданного диапазона дат (в этом виде списка списков)?

ответ

0

Если предварительная обработка с линейным временем является опцией, тогда сначала введите ключи (даты) в отдельный список. Чтобы сделать их упорядоченными, сначала конвертируйте их в datetime.

>>> from datetime import datetime 
>>> def parsedate(s): 
...  return datetime.strptime(s, '%M-%d-%Y') 
>>> keys = [parsedate(x[0]) for x in A] 

Затем вы можете сделать бинарные поиски, чтобы дешево (в O (Л.Г. п)) делать поиск диапазона:

>>> from bisect import bisect_left, bisect_right 
>>> left = bisect_left(keys, parsedate('05-22-2013')) 
>>> right = bisect_right(keys, parsedate('05-24-2013')) 

Теперь A[left:right] является диапазон вы ищете.

+0

это, безусловно, самый изящный ... отличный подход. Благодарю. – khan

+2

не работает, если срок действия составляет более 2 лет (22-22-2012> 04-22-2013) – njzk2

+0

@ njzk2: вы правы. Добавлено предположение, что OP сначала анализирует даты. –

2

Чтобы просто получить все записи списка, которые соответствуют заданной даты, вы можете создать список понимание:

print [entry for entry in A if entry[0] == '05-25-2013'] 

возвращений:

[['05-25-2013', '0.5', '0.110', '0.200'], ['05-25-2013', '0.311', '0.799', '0.426'], ['05-25-2013', '0.311', '0.091', '0.41']] 

Этот подход рассматривает только одну дату, конечно, но могут быть изменены в if для обработки дополнительных дат. Недостатком является то, что вам придется явно перечислять каждую дату в диапазоне, поскольку все они интерпретируются как простые строки.

Если вам действительно нужно, чтобы иметь возможность ввести диапазон, однако, вы должны будете получить более углубленное и, возможно, использовать модуль datetime, который будет преобразовать его в тип данных, допускающей использование > и < -как операторов.

+0

, который полностью прекрасен .... я считаю, что список ссылок всех дат, относящихся к данному диапазону дат, может использоваться как ссылка для выбора всех элементов из A. Делает это легко. Благодаря :-). – khan

+0

, если у вас есть список дат, вы можете поместить их в список и заменить свой == в if, если 'in' * – njzk2

3

Я не знаю, является ли это «лучшим» способом, потому что давайте будем честными, «лучший» - очень субъективный термин.

from datetime import date 

start_date = date(2013, 5, 22) 
end_date = date(2013, 5, 24) 

data = [] 

for i in A: 
    month, day, year = i[0].split('-') 
    record_date = date(year, month, day) 
    if record_date >= start_date and record_date <= end_date: 
     data.append(i) 
Смежные вопросы