2012-08-25 2 views
2

ВведениеСтановится ли «dropwhile»? могу ли я сделать его динамичным?

я придумал хитроумный решение моей проблемы, но не так хитер, он не работает: -/

После нескольких часов нажатия через отладчик я думаю , так что, возможно, вы можете проверить это, что причина, по которой он не работает, заключается в том, что itertools.dropwhile, после первоначального объявления, исправлено - тогда как я надеялся, что могу изменить входные параметры на предикат в каждом цикле.

Задача ниже пытается выбрать стартовую, затем последующую последующую, затем следующую начальную дату и конец после последнего ... и так далее, чтобы мы закончили серию дат интервалы, которые не перекрываются. Исходные данные берутся из одного списка и заканчиваются от другого.

следующее решение перебирает StartDates, затем над EndDates, используя dropwhile пройти через дату, которые находятся в «прошлого. Он работает отлично в первый раз. Но на втором проходе enddate застревает в '2009-12-14'. Я разразился «раньше», поэтому я мог видеть, когда он проходит тестирование, а когда нет. Не уверен, но я думаю, что происходит то, что весь тест dropwhile ставится в камень на первом проходе и не перекомпилируется на каждом проходе? Как я надеялся/ожидал.

Чтобы закончить это, я надеялся обернуть все это внутри while True и выйти с помощью исключения StopIteration, таким образом извлекая полную последовательность интервалов. Но он никогда не срабатывает. Когда я попробовал, ни один итератор не будет «дальше» до конца.

Вопросы

  1. Это (набор в камне вывод) правильно, как к тому, что происходит?
  2. Есть ли короткий, чистый, элегантный способ заставить его вести себя так, как я надеялся? Должен ли я писать свой собственный, который действует так, как я хочу?

Код

import itertools 
import datetime 

startdates = [ 
    datetime.date(2009, 11, 5), datetime.date(2009, 11, 13), 
    datetime.date(2009, 12, 4), datetime.date(2009, 12, 7), 
    datetime.date(2009, 12, 29), datetime.date(2009, 12, 30)] 

enddates = [ 
    datetime.date(2009, 10, 1), datetime.date(2009, 10, 2), 
    datetime.date(2009, 11, 4), datetime.date(2009, 12, 14), 
    datetime.date(2009, 12, 15),datetime.date(2009, 12, 30)] 

enddate = datetime.date(1900, 1, 1) 
startdate = datetime.date(1900, 1, 1) 

def isbefore(a, b): 
    return a <= b 

for startdate in itertools.dropwhile(lambda date: isbefore(date, enddate), startdates): 
    for enddate in itertools.dropwhile(lambda date: isbefore(date, startdate), enddates): 
     print startdate, enddate 
     break 

Выходной ток

2009-11-05 2009-12-14 
2009-11-13 2009-12-14 
2009-12-04 2009-12-14 
2009-12-07 2009-12-14 

Желаемая Выход

2009-11-05 2009-12-14 
2009-12-29 2009-12-30 

Более наблюдательные типы заметят, что вчера я спросил this question, который представляет ту же проблему, но это требует общего решения, тогда как на этот раз я спрашиваю конкретно о работе dropwhile.

+0

Это всегда сразу после того, как вы публикуете что-то важное: может быть, это для ..в цикле, который фиксируется - я пытаюсь изменить итератор на нем после его запуска !? –

+1

Надеюсь, я не говорю о очевидном, но вы повторно используете «startdate» и «enddate» таким образом, что это путает, нет? Я также получаю разные результаты, чем вы. –

+0

Очевидно, что начальная и конечная меняются все время. Это создает проблему? для лямбда? Могу ли я отделить эти проблемы, подав их в рутину, как раньше? Я не мог понять, как создать предикат для dropwhile, который потребляет значение без использования лямбда? –

ответ

4

Как только dropwhile сбросил предметы, которые удовлетворяют предикату, он дает остальную итерируемую неизмененную. Используя itertools.ifilterfalse на своем месте, вы получите желаемый результат, так как он будет продолжать обрабатывать предикат даже после первоначального запуска.

+0

ничего себе. это действительно работает. Благодарю. –

+2

Или он мог бы просто использовать ген xp. – Bakuriu

+0

В этом примере я действительно смог найти решение, которое вообще не нуждалось в itertools (или genexp); но это работает, достало меня и ответил на вопрос. Поставить галочку. –