реализация экспоненциального отката в Python

У меня есть два списка «начало» и «конец». Они одинаковой длины (по 4 миллиона):

for i in xrange(0,len(start)):
      print start[i], end[i]

3000027 3000162
3000162 3000186
3000186 3000187
3000187 3005000
3005000 3005020
3005020 3005090
3007000 3007186
3007186 3009000
3009000 3009500
.......

Моя проблема в том, что я хочу перебрать два списка, начиная с одной и той же точки, но постепенно перебирать «конечный список», пока не найду значение, в котором разница между «start [i]» и «end [i + x ] 'больше 1000.

введите здесь описание изображения

Я изо всех сил пытался сделать это, используя бесконечный цикл для перебора «конечного списка» до тех пор, пока разница с start не превысит 1000, а затем начну с этой точки и выполните ту же операцию оттуда ...

ПРИМЕЧАНИЕ: старое содержание опущено

В конечном итоге результат, который я ищу (взяв иллюстративный рисунок выше в качестве примера):

print density
  [4, 2, 1 ...........]

Кто-нибудь может мне с этим помочь?

ОБНОВЛЕНИЕ

Хотя предыдущий ответ на этот вопрос действительно работает:

density=[]
i_s = 0
while i_s < len(start):
     i_e = i_s
     while i_e < len(end):
         if end[i_e] - start[i_s] > 1000:
             density.append(i_e - i_s + 1)
             i_s = i_e
             break
         i_e += 1
     i_s += 1


print sum(density)/float(len(density))
print max(density)
print min(density)

Я боюсь, что код работает очень медленно, поскольку я обновляю расширение i_e, добавляя к нему 1 с каждой итерацией внутреннего цикла while ... Чтобы решить эту проблему, я хотел создать переменную счетчика, которая будет расширять переменная i_e динамически. Это будет сделано с помощью рекурсии, при которой переменная i_e будет увеличиваться экспоненциально до точки, где будет достигнута половина желаемого расстояния, а затем будет экспоненциально уменьшаться, пока не будет достигнуто желаемое расстояние.

Иллюстрация стратегии

введите здесь описание изображения

Моя попытка такова:

Я создал рекурсивную функцию для обновления счетчика переменной

counter=1 ##### initialise counter with value of 1
def exponentially_increase_decrease(start, end, counter):
    distance=end-start
    if distance<=500:  ###500 is half the desired distance
        counter=exponentially_increase_decrease(start, end, counter*2)
    else:
        counter=-exponentially_increase_decrease(start, end, counter/2)
    print counter
    return counter

Вызов функции в исходном коде:

density=[]
i_s = 0
while i_s < len(start):
     i_e = i_s
     while i_e < len(end):
         if end[i_e] - start[i_s] > 1000:
             density.append(i_e - i_s + 1)
             i_s = i_e
             break
         counter=counter=exponentially_increase_decrease(i_s, i_e, counter)
         i_e += counter
     i_s += 1

Я получаю следующую ошибку:

(Напечатано тысячи раз)

counter=exponentially_increase_decrease(start, end, counter*2)
RuntimeError: maximum recursion depth exceeded

Я не сталкивался с подобными проблемами и не уверен, правильно ли я подхожу к ним ... может ли кто-нибудь помочь?


person which_command    schedule 14.09.2017    source источник
comment
Отсортированы (упорядочены) начальный и конечный списки?   -  person Menglong Li    schedule 14.09.2017
comment
Почему не все делается с отступом после цикла while? Я думаю, так и должно быть.   -  person 9Breaker    schedule 14.09.2017
comment
извиняюсь, код имеет отступ, как и должно быть сейчас, и да, оба списка отсортированы   -  person which_command    schedule 14.09.2017
comment
Я просто не понимаю того, что вы пытаетесь сделать. Почему 4005090 в конечном списке по сравнению с 300500 в начальном списке справа на 1 позицию позади соответствует условию?   -  person dabadaba    schedule 14.09.2017
comment
Извините, 4 в 4005090 должно быть 3, я исправлю это как можно быстрее   -  person which_command    schedule 14.09.2017
comment
Какой результат вы ищете? Я все еще не понимаю.   -  person juanpa.arrivillaga    schedule 14.09.2017
comment
Должен ли поиск в end начинаться с текущего индекса в start? Другими словами, нужно ли counter равняться i каждый раз, когда вы запускаете внутренний цикл while?   -  person RagingRoosevelt    schedule 14.09.2017
comment
да, переменные итератора counter и i должны быть одинаковыми каждый раз при запуске цикла while   -  person which_command    schedule 14.09.2017
comment
Я добавил ожидаемый результат внизу вопроса   -  person which_command    schedule 14.09.2017
comment
Должно ли расстояние 2 в вашем примере изображения действительно быть 3?   -  person RagingRoosevelt    schedule 14.09.2017
comment
извините, снова вы правы, расстояние должно быть 3, а не 2   -  person which_command    schedule 14.09.2017


Ответы (2)


Это один из немногих случаев, когда я считаю, что цикл while более прямолинейный, поскольку i_e и i_s зависят друг от друга. Вы можете использовать два range итератора и продвигать первый по тому, сколько вы израсходовали от второго, но это кажется слишком сложным.

>>> start
[3000027, 3000162, 3000186, 3000187, 3005000, 3005020, 3007000, 3007186, 3009000]
>>> end
[3000162, 3000186, 3000187, 3005000, 3005020, 3005090, 3007186, 3009000, 3009500]
>>> i_s = 0
>>> while i_s < len(start):
...     i_e = i_s
...     while i_e < len(end):
...         if end[i_e] - start[i_s] > 1000:
...             print(i_e - i_s + 1)
...             i_s = i_e
...             break
...         i_e += 1
...     i_s += 1
...
4
3
1
person juanpa.arrivillaga    schedule 14.09.2017
comment
хорошо, если вы собираетесь использовать while, вы можете переместить условие end[i_e] - start[i_s] >= 1000 в while, чтобы break - person dabadaba; 14.09.2017
comment
@dabadaba хм, может, я слишком много думаю, но что, если это условие никогда не будет выполнено? - person juanpa.arrivillaga; 14.09.2017
comment
ну тогда это исчерпает список, я думаю? - person dabadaba; 14.09.2017
comment
@dabadaba Вы выдадите ошибку, когда попытаетесь проиндексировать список ... Нет итератора списка, который нужно исчерпать ... - person juanpa.arrivillaga; 14.09.2017
comment
но вы уже проверяете i_e < len(end), он не выйдет за пределы - person dabadaba; 14.09.2017
comment
@dabadaba, тогда я не понимаю, что вы имеете в виду, говоря о переносе условия на время, разве это не заменит i_e < len(end)? Или вы имеете в виду использование and? - person juanpa.arrivillaga; 14.09.2017
comment
@dabadaba да, но тогда ты всегда _1 _... Я не уверен, что ты этого хочешь. Опять же, возможно, я слишком много об этом думаю, но в любом случае я бы, вероятно, придерживался вышеизложенного, потому что моя ментальная логика транслитерируется в код. - person juanpa.arrivillaga; 14.09.2017

Не уверен, правильно ли я понял ... Это то, что вы ищете?

MAX_DIFF = 1000
density = [0] * len(start)
for i in range(len(start)):
    for j in range(i, len(end)):
        density[i] += 1
        if end[i] - start[i] >= MAX_DIFF:
            break
print(density)
person jdehesa    schedule 14.09.2017
comment
OP хочет сохранить список len(start) в памяти? (s) он сказал, что списки состоят из 4 миллионов элементов - person dabadaba; 14.09.2017
comment
@dabadaba Ну, я не могу сказать наверняка, но это, кажется, ожидаемый результат? ... Но да, при необходимости он может быть выражен как генератор. - person jdehesa; 14.09.2017