Я хотел бы построить функцию в matplotlib
, но только в диапазоне, ограниченном двумя числами с плавающей запятой, скажем 2.6
и 8.2
. Для этого мне нужен список или генератор, который включает в себя две границы с плавающей запятой, например
[2.6, 3, 4, 5, 6, 7, 8, 8.2]
Я знаю, что это можно сделать вот так
lst = [2.6]
lst.extend(list(range(ceil(2.6), ceil(8.2))))
lst.append(8.2)
но это очень необычно. Есть ли лучший питонический способ сделать это?
Ваши требования необычны, поэтому, возможно, следует ожидать необычного решения.
@JohnColeman Возможно, ты прав. То, что мне на самом деле нужно, на самом деле не так уж и странно - я хочу построить функцию в matplotlib, но только в определенном диапазоне с плавающей запятой.
@ user2357112 Я отредактировал вопрос, чтобы прояснить мои требования.
Если вам это нужно для построения графиков, то почему вас волнует, являются ли промежуточные точки целыми числами? Не было бы разумнее иметь точки, расположенные на равном расстоянии друг от друга?
Вы можете написать это как lst = [2.6, *range(floor(2.6) + 1, ceil(8.2)), 8.2]
и заменить числа переменными. Однако ошибки округления могут привести к неверным результатам.
Ваши требования вообще не ясны. Поскольку, похоже, у вас есть рабочий пример, можете ли вы включить минимально воспроизводимый пример с сюжетом в ваш вопрос? plt.xlim(2.6, 8.2)
может быть всем, что вам нужно, если вы используете range(10)
для своих значений x.
@JohnColeman На самом деле эти диапазоны имеют разную длину, поэтому количество точек зависит от диапазона. Кроме того, поскольку я рисую дважды (один раз для всего диапазона черным цветом и один раз только для указанного диапазона другим цветом), было бы хорошо, чтобы точки рисования для этих двух графиков совпадали.
Дополнительные обобщения распаковки PEP 448 делают это хотя бы немного менее многословным:
lst = [2.6, *range(ceil(2.6), ceil(8.2)), 8.2]
Я бы лично обернул его в функцию и задокументировал, что/почему вы это делаете, но он отлично работает в виде встроенного кода, если предположить, что код имеет больше смысла в контексте, чем отсутствие контекста здесь.
Если ленивая генерация (один проход, отсутствие сбора в памяти) приемлема/желательна, вы можете использовать itertools.chain
, чтобы создать итератор, производящий те же значения:
from itertools import chain
gen = chain([2.6], range(ceil(2.6), ceil(8.2)), [8.2])
Если предоставляемые значения сами могут быть четными целыми числами, вы можете использовать math.nextafter, чтобы гарантировать, что границы range
не перекрывают начальную точку, изменив range
на:
range(ceil(math.nextafter(2.6, math.inf)), ceil(8.2))
для любого решения выше.
Кстати, вызов list
в исходном коде был избыточным; .extend
принимает любую итерацию, как и конструктор list
, поэтому, если вы можете сначала преобразовать его в list
, вы можете передать его extend
напрямую и избежать временного list
.
Это ленивая генерация, но я предпочитаю простоту кода экономии памяти (если только речь не идет об огромных списках).
nextafter
кажется сложнее, чем floor(2.6) + 1
.
@nocomment: Конечно, все, что плывет на вашей лодке. Я чувствовал, что логика nextafter
+ceil
более точно соответствует логическому замыслу, но, конечно, это работает в любом случае.
Если границы
0.0
и10.0
, каким должен быть результат? Должен ли вывод начинаться с[0.0, 0
,[0.0, 1
или чего-то еще? Должно ли оно заканчиваться на9, 10.0]
,10, 10.0]
,9]
или на что-то еще?