Avatar ·

Есть ли в JavaScript функция range() для генерации последовательности чисел?

Всем привет! Я новичок в JavaScript, перешёл с Python. Там есть очень удобная встроенная функция `range()`, которая позволяет легко создать последовательность чисел, например: ```python for i in range(5): print(i) # 0, 1, 2, 3, 4 my_list = list(range(2, 10, 2)) # [2, 4, 6, 8] ``` Теперь я пишу на JavaScript и мне нужно сделать нечто подобное. Например, создать массив чисел от 1 до 10, или пройтись в цикле от 0 до 20 с шагом 3. Я пробовал гуглить, но не нашёл встроенного метода. Пока я делаю так: ```javascript let arr = []; for (let i = 0; i < 10; i++) { arr.push(i); } ``` Это работает, но выглядит громоздко. Особенно когда нужно генерировать диапазоны с разными шагами или в обратном порядке. Мне кажется, что в таком современном языке, как JavaScript, должна быть какая-то элегантная утилита для этого. Подскажите, есть ли в JavaScript нативная функция `range()` или какой-то стандартный способ сгенерировать массив чисел от A до B с определённым шагом? Может, есть какие-то хитрости с методами массивов или современными возможностями ES6+? Заранее спасибо за помощь! <<>>

Короткий ответ: нет нативной функции, но есть отличные альтернативы

В JavaScript действительно нет встроенной функции range(), как в Python или Ruby. Однако, начиная с ES6, у нас есть несколько элегантных способов решить эту задачу. Вот лучшие из них:

Способ 1: Используем Array.from() (рекомендуемый)

Самый чистый и современный подход — использовать статический метод Array.from() вместе с генератором ключей:

// Простой диапазон от 0 до 9
const range1 = Array.from({ length: 10 }, (_, i) => i);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

// Диапазон от 5 до 15
const range2 = Array.from({ length: 11 }, (_, i) => i + 5);
// [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

// С шагом 3 от 0 до 30
const range3 = Array.from({ length: 11 }, (_, i) => i * 3);
// [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30]

Способ 2: Универсальная функция-помощник

Лучше всего написать свою небольшую утилиту, которую можно переиспользовать:

function range(start, end, step = 1) {
    // Если передан только один аргумент, считаем его концом, а start = 0
    if (end === undefined) {
        end = start;
        start = 0;
    }
    
    // Вычисляем длину массива
    const length = Math.ceil((end - start) / step);
    
    return Array.from({ length }, (_, i) => start + i * step);
}

// Примеры использования:
console.log(range(5));          // [0, 1, 2, 3, 4]
console.log(range(2, 10));      // [2, 3, 4, 5, 6, 7, 8, 9]
console.log(range(0, 10, 2));   // [0, 2, 4, 6, 8]
console.log(range(10, 0, -1));  // [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

Способ 3: Через оператор spread и keys()

Хотя этот способ менее гибкий, он очень лаконичный для простых случаев:

// От 0 до 9
const arr = [...Array(10).keys()];
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Способ 4: Смещение с помощью map()

Если нужно задать начальное значение:

const start = 5;
const end = 15;
const range = [...Array(end - start + 1)].map((_, i) => i + start);
// [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

Что выбрать?

  • Для разового использования — Array.from() с длиной и колбэком. Это понятно и эффективно.
  • Для частого использования — напишите свою функцию range() один раз и используйте её везде. Я рекомендую вариант из Способа 2.
  • Если работаете с большими диапазонами — рассмотрите генераторы (см. альтернативный ответ ниже), чтобы не хранить весь массив в памяти.

Важное замечание про производительность

Все эти методы работают за O(n) и создают новый массив. Для большинства задач это нормально. Но если вам нужно генерировать диапазоны из миллионов элементов, лучше использовать генераторы, чтобы не забивать память.

<<>>

Альтернатива: Генераторы для ленивых диапазонов

Если вы работаете с очень большими диапазонами или хотите экономить память, используйте функции-генераторы. Они не создают массив целиком, а выдают значения по одному:

function* rangeGenerator(start, end, step = 1) {
    if (end === undefined) {
        end = start;
        start = 0;
    }
    
    for (let i = start; i < end; i += step) {
        yield i;
    }
}

// Использование:
for (const num of rangeGenerator(0, 10, 2)) {
    console.log(num); // 0, 2, 4, 6, 8
}

// Преобразование в массив (если нужно):
const arr = [...rangeGenerator(1, 6)]; // [1, 2, 3, 4, 5]

Для любителей функционального программирования

Можно также использовать библиотеки вроде lodash или ramda, где уже есть готовая функция _.range():

// С lodash
_.range(4);        // [0, 1, 2, 3]
_.range(1, 5);     // [1, 2, 3, 4]
_.range(0, 20, 5); // [0, 5, 10, 15]

Но если вы не хотите подключать целую библиотеку ради одной функции, лучше написать свою — это займёт 3 строки кода.