IntRangeParser разбирает строку с целыми числами и диапазонами и возвращает отсортированный список уникальных значений.
Метод не бросает исключения для ошибок пользовательского ввода. Ошибки валидации возвращаются через Result<List<int>>.
Result<List<int>> IntRangeParser.Parse(string? rangeSource, int maxRangeValue);
Result<List<int>> IntRangeParser.Parse(
string? rangeSource,
int maxRangeValue,
int maxResultCount);Первая перегрузка сохраняет базовое поведение и ограничивает только допустимую верхнюю границу диапазона.
Вторая перегрузка дополнительно ограничивает максимальное количество уникальных значений в результате. Она предназначена для сценариев с недоверенным вводом, где нельзя позволять пользователю запросить слишком большой материализованный список.
Пример для недоверенного ввода:
var result = IntRangeParser.Parse(
rangeSource: userInput,
maxRangeValue: 1_000_000,
maxResultCount: 10_000);Если результат содержит больше maxResultCount уникальных значений, метод возвращает Failure.
Поддерживаются токены следующих видов:
N— одиночное число;N-M— диапазон отNдоM;-N— открытый слева диапазон;N-— открытый справа диапазон.
Токены могут быть разделены любым символом из набора:
" ,.;_:#!|\\/'\""Примеры:
1,2,31;2;31 2 31|2|3
Добавляется одно значение.
Примеры:
5->[5]0->[0]
Добавляются все значения от меньшей границы к большей включительно.
Примеры:
3-7->[3,4,5,6,7]7-3->[3,4,5,6,7]
Интерпретируется как диапазон от 1 до N.
Примеры:
-5->[1,2,3,4,5]-1->[1]
-0 считается ошибкой.
Интерпретируется как диапазон от N до maxRangeValue.
Примеры:
10-,maxRangeValue = 15->[10,11,12,13,14,15]0-,maxRangeValue = 5->[0,1,2,3,4,5]
Ноль допустим только при явном указании:
00-N0-
Примеры:
0->[0]0-3->[0,1,2,3]0-,maxRangeValue = 3->[0,1,2,3]
Явно отрицательные значения и границы не поддерживаются. Любая попытка задать значение меньше 0 считается ошибкой.
Примеры некорректного ввода:
1--5--5-1-5
Важно: запись -N в начале строки — это не отрицательное число, а специальная форма открытого слева диапазона.
maxRangeValue должен быть не меньше 0.
Все явно указанные значения должны лежать в диапазоне:
0..maxRangeValue
Исключение: у формы -N левая граница неявная и всегда равна 1.
Примеры:
5,maxRangeValue = 10-> ok0-10,maxRangeValue = 10-> ok11,maxRangeValue = 10-> error5-12,maxRangeValue = 10-> error-12,maxRangeValue = 10-> error
maxResultCount доступен только во второй перегрузке и должен быть не меньше 0.
Лимит применяется к итоговому количеству уникальных значений. Если лимит превышен, метод возвращает Failure. Парсер старается отказывать как можно раньше: для одного диапазона лимит проверяется до материализации результата, а в потоковом сценарии — после обработки очередного токена.
Примеры:
IntRangeParser.Parse("1-100", maxRangeValue: 100, maxResultCount: 100); // ok
IntRangeParser.Parse("1-100", maxRangeValue: 100, maxResultCount: 99); // Failure
IntRangeParser.Parse("", maxRangeValue: 100, maxResultCount: 0); // ok, пустой список
IntRangeParser.Parse("0", maxRangeValue: 100, maxResultCount: 0); // FailureОткрытый слева диапазон допустим только первым токеном.
Примеры:
-5,10-> ok10,-5-> error
Открытый справа диапазон допустим только последним токеном.
Примеры:
5,10--> ok10-,15-> error
Пробелы вокруг - внутри диапазона допустимы. Поддерживаются, например:
10 - 2010- 2010 -20- 2010 -
Перед разбором пробелы, непосредственно примыкающие к -, игнорируются.
Важно:
- пробелы вокруг
-не считаются разделителями токенов; - пробелы вне диапазонной конструкции остаются обычными разделителями.
Примеры:
10 - 20 30-> токены10-20и301 2 3-> три отдельных токена
Результат всегда:
- без дубликатов;
- отсортирован по возрастанию.
Примеры:
1,2,2,3->[1,2,3]5-7,6,7,8->[5,6,7,8]
Метод возвращает Failure, если:
rangeSource == null;maxRangeValue < 0;maxResultCount < 0;- встречен некорректный токен;
- в токене больше одного символа
-; - токен невозможно распарсить как число или диапазон;
- токен нарушает позиционные правила (
-Nне первый,N-не последний); - явная граница выходит за пределы
0..maxRangeValue; - обнаружена попытка задать отрицательное значение;
- встречен
-0; - результат содержит больше значений, чем разрешено параметром
maxResultCount; - результат слишком велик для размещения в
List<int>.
var result = IntRangeParser.Parse("1,2,5-7", 10);Результат:
[1,2,5,6,7]var result = IntRangeParser.Parse("-5,10-", 12);Результат:
[1,2,3,4,5,10,11,12]var result = IntRangeParser.Parse("0-3, 10 - 12", 20);Результат:
[0,1,2,3,10,11,12]var result = IntRangeParser.Parse("7-3", 10);Результат:
[3,4,5,6,7]var result = IntRangeParser.Parse("10,-5", 20);Результат:
FailureПричина: -N допустим только первым токеном.
var result = IntRangeParser.Parse("-0", 20);Результат:
FailureПричина: открытый слева диапазон начинается с 1, -0 недопустим.
var result = IntRangeParser.Parse("1-1000", 10_000, maxResultCount: 100);Результат:
FailureПричина: результат содержит больше значений, чем разрешено параметром maxResultCount.
Внутри парсер оптимизирован под int и сценарии:
- небольшие и средние диапазоны;
- большие плотные диапазоны;
- большие, но разрежённые диапазоны.
Для этого используются разные внутренние стратегии материализации результата, но это не влияет на публичный контракт метода.