Перебирать диапазоны и возвращать те, которых нет в любом диапазоне?

У меня есть список поплавков.

      values = [2.3, 6.4, 11.3]

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

То, что у меня есть до сих пор,

      not_in_range =[]
for x in values:
        pre = float(x - delta)
        post = float(x + delta)
        for y in numpy.arange(0,15,0.5):
                if (pre <= y <= post) == True:
                        pass
                else:
                        not_in_range.append(y)

Но, очевидно, это не работает по нескольким причинам: избыточность, не проверяет все диапазоны сразу и т. Д. Я новичок в кодировании и изо всех сил пытаюсь мыслить достаточно абстрактно, чтобы решить эту проблему. Мы будем очень благодарны за любую помощь в составлении плана действий.

ИЗМЕНИТЬ Для ясности мне нужен список диапазонов от каждого значения (или, может быть, массив numpy?) Как

      [0.3, 4.3]
[4.4, 8.4]
[9.3, 13.3]

И чтобы вернуть любое число с плавающей запятой от 0 до 15 с шагом 0,5, которое не попадает ни в один из этих диапазонов, поэтому окончательный результат будет следующим:

      not_in_ranges = [0, 8.5, 9, 13.5, 14, 14.5] 

3 ответа

Я сделал сравнительный анализ (в ноутбуке jupyter). Посмотрите результаты.

      # First cell
import numpy as np
values = np.random.randn(1000000)
values.shape

# Second cell
%%time
not_in_range =[]
for x in values:
        pre = float(x - 2)
        post = float(x + 2)
        for y in np.arange(0,15,0.5):
                if (pre <= y <= post) == True:
                        pass
                else:
                        not_in_range.append(y)
# Second cell output - Wall time: 37.2 s

# Third cell
%%time
pre = values - 2
post = values + 2

whole_range = np.arange(0,15,0.5)
whole_range

search_range = []
for pr, po in zip(pre, post):
    pr = (int(pr) + 0.5) if (pr%5) else int(pr) 
    po = (int(po) + 0.5) if (po%5) else int(po) 
    search_range += list(np.arange(pr, po, 0.5))
    
whole_range = set(whole_range)
search_range = set(search_range)
print(whole_range.difference(search_range))

# Third cell output - Wall time: 3.99 s

Чтобы сгенерировать список диапазонов, вы можете быстро понять список:

      ranges = [[x-2, x+2] for x in values]

## [[0.3, 4.3], [4.4, 8.4], [9.3, 13.3]]

Затем, чтобы вернуть любое число с плавающей запятой от 0 до 15 (с шагом 0,5), которое не попадает ни в один из диапазонов , вы можете использовать:

      not_in_ranges = []
for y in numpy.arange(0, 15, 0.5):      # for all desired values to check
  if not any(pre < y and y < post for pre, post in ranges):
    not_in_ranges.append(y)             # if it is in none of the intervals, append it

## [0.0, 8.5, 9.0, 13.5, 14.0, 14.5]

Explanation: Это перебирает каждое из возможных значений и добавляет его к not_in_rangesсписок, если его нет ни в одном из интервалов. Чтобы проверить, находится ли он в интервалах, я использую встроенную функцию python any чтобы проверить, есть ли в списке какие-либо значения до и после ranges которые возвращают True, когда pre < y < post (т.е. если yнаходится в любом из интервалов). Если это False, то он не помещается ни в один из интервалов и поэтому добавляется в список таких значений.


В качестве альтернативы , если вам нужен только результат (а не оба списка), вы можете объединить их с чем-то вроде:

      not_in_ranges = []
for y in numpy.arange(0, 15, 0.5):
  if not any(x-2 < y and y < x+2 for x in values):
    not_in_ranges.append(y)

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

      not_in_ranges = [y for y in numpy.arange(0, 15, 0.5) if not any(x-2 < y and y < x+2 for x in values)]

Обратите внимание, что последний из них, вероятно, будет выполняться быстрее всего, поскольку вызов добавления выполняется довольно медленно, а понимание списка почти всегда происходит быстрее. Хотя это, конечно, может быть не так просто понять с первого взгляда, если вы еще не привыкли к формату понимания списка Python.

Вы можете использовать библиотеку интервалов intvalpy

      from intvalpy import Interval
import numpy as np

values = [2.3, 6.4, 11.3]
delta = 2
intervals = values + Interval(-delta, delta)

not_in_ranges = []
for k in np.arange(0, 15, 0.5):
    if not k in intervals:
        not_in_ranges.append(k)
print(not_in_ranges)

Интервалы создаются в соответствии с конструктивными определениями интервальных арифметических операций. В in Оператор проверяет, содержится ли точка (или интервал) в другом интервале.

Другие вопросы по тегам