Как создать массив, содержащий 1 ... N - PullRequest
849 голосов
/ 19 сентября 2010

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

var foo = [];

for (var i = 1; i <= N; i++) {
   foo.push(i);
}

Мне кажется, что должен быть способ сделать это без цикла.

Ответы [ 56 ]

39 голосов
/ 28 декабря 2012

Если вы используете d3.js в вашем приложении, как я, D3 предоставляет вспомогательную функцию, которая делает это за вас.

Таким образом, чтобы получить массив от 0 до4, это так же просто, как:

d3.range(5)
[0, 1, 2, 3, 4]

и получить массив от 1 до 5, как вы и просили:

d3.range(1, 5+1)
[1, 2, 3, 4, 5]

Изучите это руководство для получения дополнительной информации.

38 голосов
/ 05 марта 2019

На этот вопрос есть много сложных ответов, но простая однострочная:

[...Array(255).keys()].map(x => x + 1)

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

127, Int8,

255, Uint8,

32,767, Int16,

65,535, Uint16,

2 147 483 647, Int32,

4 294 967 295, Uint32.

(на основе макс. Целочисленных значений ), а также подробнее о типизированных массивах):

(new Uint8Array(255)).map(($,i) => i + 1);

Хотя это решение также не столь идеально, поскольку оно создает два массива и использует дополнительное объявление переменной "$" (не уверен, что каким-либо образом обойти это, используя этот метод).Я думаю, что следующее решение является абсолютно быстрым из возможных способов сделать это:

for(var i = 0, arr = new Uint8Array(255); i < arr.length; i++) arr[i] = i + 1;

В любое время после того, как это заявление сделано, вы можете просто использовать переменную "arr" в текущей области;

Если вы хотите сделать из него простую функцию (с некоторой базовой проверкой):

function range(min, max) {
    min = min && min.constructor == Number ? min : 0;
    !(max && max.constructor == Number && max > min) && // boolean statements can also be used with void return types, like a one-line if statement.
        ((max = min) & (min = 0));  //if there is a "max" argument specified, then first check if its a number and if its graeter than min: if so, stay the same; if not, then consider it as if there is no "max" in the first place, and "max" becomes "min" (and min becomes 0 by default)

    for(var i = 0, arr = new (
        max < 128 ? Int8Array : 
        max < 256 ? Uint8Array :
        max < 32768 ? Int16Array : 
        max < 65536 ? Uint16Array :
        max < 2147483648 ? Int32Array :
        max < 4294967296 ? Uint32Array : 
        Array
    )(max - min); i < arr.length; i++) arr[i] = i + min;
    return arr;
}



//and you can loop through it easily using array methods if you want
range(1,11).forEach(x => console.log(x));

//or if you're used to pythons `for...in` you can do a similar thing with `for...of` if you want the individual values:
for(i of range(2020,2025)) console.log(i);

//or if you really want to use `for..in`, you can, but then you will only be accessing the keys:

for(k in range(25,30)) console.log(k);

console.log(
    range(1,128).constructor.name,
    range(200).constructor.name,
    range(400,900).constructor.name,
    range(33333).constructor.name,
    range(823, 100000).constructor.name,
    range(10,4) // when the "min" argument is greater than the "max", then it just considers it as if there is no "max", and the new max becomes "min", and "min" becomes 0, as if "max" was never even written
);

, так что с помощью вышеуказанной функции вышеуказанный супер-медленный "простой однострочный" становится супер-быстрым, даже короче:

range(1,14000);
38 голосов
/ 19 марта 2018

ES6 это сделает свое дело:

[...Array(12).keys()]

проверить результат:

[...Array(12).keys()].map(number => console.log(number))
37 голосов
/ 03 июня 2013

Это, вероятно, самый быстрый способ создания массива чисел

Кратчайший

var a=[],b=N;while(b--)a[b]=b+1;

Встроенный

var arr=(function(a,b){while(a--)b[a]=a;return b})(10,[]);
//arr=[0,1,2,3,4,5,6,7,8,9]

Если вы хотитеначать с 1

var arr=(function(a,b){while(a--)b[a]=a+1;return b})(10,[]);
//arr=[1,2,3,4,5,6,7,8,9,10]

Хотите функцию?

function range(a,b,c){c=[];while(a--)c[a]=a+b;return c}; //length,start,placeholder
var arr=range(10,5);
//arr=[5,6,7,8,9,10,11,12,13,14]

ПОЧЕМУ?

  1. while isсамая быстрая петля

  2. Прямая настройка быстрее, чем push

  3. [] быстрее new Array(10)

  4. это коротко ... посмотрите первый код.затем посмотрите на все остальные функции здесь.

Если вы не можете жить без для

for(var a=[],b=7;b>0;a[--b]=b+1); //a=[1,2,3,4,5,6,7]

или

for(var a=[],b=7;b--;a[b]=b+1); //a=[1,2,3,4,5,6,7]
36 голосов
/ 23 ноября 2016

Использование оператора распространения ES2015 / ES6

[...Array(10)].map((_, i) => i + 1)

console.log([...Array(10)].map((_, i) => i + 1))
30 голосов
/ 01 ноября 2018

Новый способ заполнения Array - это:

const array = [...Array(5).keys()]
console.log(array)

результат будет: [0, 1, 2, 3, 4]

29 голосов
/ 02 августа 2016

Если вы используете lodash, вы можете использовать _. Range :

_.range([start=0], end, [step=1])

Создает массив чисел (положительный и / или отрицательный) прогресс от начала до, но не в том числе, конец. Шаг -1 используется, если указано отрицательное начало без конца или шага. Если конец не указан, он запускается с запуском затем установите на 0.

Примеры:

_.range(4);
// ➜ [0, 1, 2, 3]

_.range(-4);
// ➜ [0, -1, -2, -3]

_.range(1, 5);
// ➜ [1, 2, 3, 4]

_.range(0, 20, 5);
// ➜ [0, 5, 10, 15]

_.range(0, -4, -1);
// ➜ [0, -1, -2, -3]

_.range(1, 4, 0);
// ➜ [1, 1, 1]

_.range(0);
// ➜ []
25 голосов
/ 19 февраля 2016

Итоговый сводный отчет. Drrruummm Rolll -

Это кратчайший код для генерации массива размера N (здесь 10) без использования ES6 . Cocco версия выше близка, но не самая короткая.

(function(n){for(a=[];n--;a[n]=n+1);return a})(10)

Но бесспорный победитель этого гольф-кода (соревнование для решения конкретной проблемы в наименьшем количестве байтов исходного кода) - Нико Руотсалайнен . Использование Array Constructor и оператора распространения ES6 . (Большая часть синтаксиса ES6 является допустимым typeScript, но следующее - нет. Поэтому будьте осторожны при его использовании)

[...Array(10).keys()]
18 голосов
/ 29 марта 2016

В ES6 есть еще один способ, использующий Array.from , который принимает 2 аргумента, первый - это arrayLike (в данном случае объект со свойством length), а второй - функция отображения(в этом случае мы сопоставляем элемент с его индексом)

Array.from({length:10}, (v,i) => i)

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

Array.from({length:10}, (v,i) => i*2)

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

// open the dev console to see results

count = 100000

console.time("from object")
for (let i = 0; i<count; i++) {
  range = Array.from({length:10}, (v,i) => i )
}
console.timeEnd("from object")

console.time("from keys")
for (let i =0; i<count; i++) {
  range = Array.from(Array(10).keys())
}
console.timeEnd("from keys")

console.time("apply")
for (let i = 0; i<count; i++) {
  range = Array.apply(null, { length: 10 }).map(function(element, index) { return index; })
}
console.timeEnd("apply")
13 голосов
/ 23 декабря 2016
for(var i,a=[i=0];i<10;a[i++]=i);

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

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