Перебирать диапазоны и возвращать те, которых нет в любом диапазоне?
У меня есть список поплавков.
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
Оператор проверяет, содержится ли точка (или интервал) в другом интервале.