Как создать массив, содержащий 1... N

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

var foo = [];

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

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

806
19 сент. '10 в 20:34
источник поделиться
55 ответов
  • 1
  • 2

Если я получу то, что вам нужно, вам понадобится массив чисел 1..n который вы можете позже просмотреть.

Если это все, что вам нужно, вы можете сделать это вместо этого?

var foo = new Array(45); // create an empty array with length 45

затем, когда вы хотите использовать его... (без оптимизации, например)

for(var i = 0; i < foo.length; i++){
  document.write('Item: ' + (i + 1) + ' of ' + foo.length + '<br/>'); 
}

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

Смотрите это в действии здесь: http://jsfiddle.net/3kcvm/

263
19 сент. '10 в 20:54
источник

Связанные вопросы


Похожие вопросы

Вы можете сделать это:

var N = 10; 
Array.apply(null, {length: N}).map(Number.call, Number)

результат: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

или со случайными значениями:

Array.apply(null, {length: N}).map(Function.call, Math.random)

результат: [0.7082694901619107, 0.9572225909214467, 0.8586748542729765, 0,8653848143294454, 0,008339877473190427, 0,9911756622605026, 0,8133423360995948, 0,8377588465809822, 0,5577575915958732, 0,16363654541783035]

Объяснение

Во-первых, обратите внимание, что Number.call(undefined, N) эквивалентно Number(N), который просто возвращает N. Мы будем использовать этот факт позже.

Array.apply(null, [undefined, undefined, undefined]) эквивалентен Array(undefined, undefined, undefined), который создает трехэлементный массив и присваивает каждому элементу undefined.

Как вы можете обобщить это на N элементов? Подумайте, как работает Array(), что происходит примерно так:

function Array() {
    if ( arguments.length == 1 &&
         'number' === typeof arguments[0] &&
         arguments[0] >= 0 && arguments &&
         arguments[0] < 1 << 32 ) {
        return [ … ];  // array of length arguments[0], generated by native code
    }
    var a = [];
    for (var i = 0; i < arguments.length; i++) {
        a.push(arguments[i]);
    }
    return a;
}

Так как ECMAScript 5, Function.prototype.apply(thisArg, argsArray) также принимает в качестве второго параметра объект типа, подобный утину. Если мы вызываем Array.apply(null, { length: N }), то он выполнит

function Array() {
    var a = [];
    for (var i = 0; i < /* arguments.length = */ N; i++) {
        a.push(/* arguments[i] = */ undefined);
    }
    return a;
}

Теперь у нас есть N-элементный массив, каждый элемент которого установлен в undefined. Когда мы назовем .map(callback, thisArg), каждый элемент будет установлен на результат callback.call(thisArg, element, index, array). Следовательно, [undefined, undefined, …, undefined].map(Number.call, Number) будет отображать каждый элемент в (Number.call).call(Number, undefined, index, array), что совпадает с Number.call(undefined, index, array), который, как мы видели ранее, оценивается как index. Это завершает массив, элементы которого совпадают с их индексом.

Зачем решать проблему Array.apply(null, {length: N}) вместо Array(N)? В конце концов, оба выражения приведут к массиву N элементов из элементов undefined. Разница в том, что в первом выражении каждый элемент явно установлен в undefined, тогда как в последнем каждый элемент никогда не был установлен. Согласно документации .map():

callback вызывается только для индексов массива, которым присвоены значения; он не вызывается для индексов, которые были удалены или которые никогда не были назначены значения.

Следовательно, Array(N) недостаточно; Array(N).map(Number.call, Number) приведет к неинициализированному массиву длины N.

Совместимость

Поскольку этот метод основан на поведении Function.prototype.apply(), указанном в ECMAScript 5, он будет не работать в браузерах до ECMAScript 5, таких как Chrome 14 и Internet Explorer 9.

790
19 нояб. '13 в 11:33
источник

В ES6 с использованием методов Array from() и ().

Array.from(Array(10).keys())
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Более короткая версия с помощью оператора распространения.

[...Array(10).keys()]
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
754
26 окт. '15 в 21:03
источник

Простой и краткий путь в ES6:

Array.from({length: 5}, (v, k) => k+1); 
// [1,2,3,4,5]

Таким образом:

    Array.from({length: N}, (v, k) => k+1);  
   // [1,2,3,...,N]

Поскольку массив инициализируется с undefined на каждой позиции, значение v будет undefined

const range = (N) => Array.from({length: N}, (v, k) => k+1) ;

console.log(
  range(5)
)
292
06 июля '16 в 0:38
источник

В ES6 вы можете:

Array(N).fill().map((e,i)=>i+1);

http://jsbin.com/molabiluwa/edit?js,console

Изменение: Изменен Array(45) до Array(N) так как вы обновили вопрос.

console.log(
  Array(45).fill(0).map((e,i)=>i+1)
);
166
21 дек. '15 в 6:18
источник

Я знаю, что ваш вопрос заключается в том, чтобы заполнить массив численно, но я не знаю, почему вы хотите это сделать.

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


Это говорит о том, что для ваших нужд вы можете просто объявить массив определенного размера:

var foo = new Array(N);   // where N is a positive integer

/* this will create an array of size, N, primarily for memory allocation, 
   but does not create any defined values

   foo.length                                // size of Array
   foo[ Math.floor(foo.length/2) ] = 'value' // places value in the middle of the array
*/


ES6

распространение

Используя метод оператора spread (...) и keys, вы можете создать временный массив размера N для создания индексов, а затем новый массив, который может быть назначен вашей переменной:

var foo = [ ...Array(N).keys() ];

Заполните/Карта

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

var foo = Array(N).fill().map((v,i)=>i);

Array.from

Это должно быть инициализировано длиной N и заполнением массива за один проход.

Array.from({ length: N }, (v, i) => i)
136
19 сент. '10 в 21:06
источник

Используйте очень популярный метод подчёркивания _.range

// _.range([start], stop, [step])

_.range(10); // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_.range(1, 11); // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_.range(0, 30, 5); // => [0, 5, 10, 15, 20, 25]
_.range(0, -10, -1); //  => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
_.range(0); // => []
101
27 июня '14 в 1:05
источник
function range(start, end) {
    var foo = [];
    for (var i = start; i <= end; i++) {
        foo.push(i);
    }
    return foo;
}

Затем вызывается

var foo = range(1, 5);

В Javascript нет встроенного способа сделать это, но это совершенно правильная функция полезности для создания, если вам нужно сделать это более одного раза.

Изменить: На мой взгляд, следующая лучшая функция диапазона. Возможно, только потому, что я склонен к LINQ, но я думаю, что это более полезно в большем количестве случаев. Ваш пробег может отличаться.

function range(start, count) {
    if(arguments.length == 1) {
        count = start;
        start = 0;
    }

    var foo = [];
    for (var i = 0; i < count; i++) {
        foo.push(start + i);
    }
    return foo;
}
63
19 сент. '10 в 20:41
источник

самый быстрый способ заполнить Array в v8:

[...Array(5)].map((_,i) => i);

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

52
28 авг. '18 в 0:35
источник

Вы можете использовать это:

new Array(/*any number which you want*/)
    .join().split(',')
    .map(function(item, index){ return ++index;})

например

new Array(10)
    .join().split(',')
    .map(function(item, index){ return ++index;})

создаст следующий массив:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
43
19 марта '14 в 11:17
источник

ES6 это сделает трюк:

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

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

[...Array(12).keys()].map(number => console.log(number))
38
19 марта '18 в 13:30
источник

Если вы используете 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
28 дек. '12 в 1:41
источник

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

самый короткий

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 самая быстрая петля

  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]
37
03 июня '13 в 19:40
источник

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

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

console.log([...Array(10)].map((_, i) => i + 1))
32
23 нояб. '16 в 22:15
источник

Если вы используете 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);
// ➜ []
29
02 авг. '16 в 21:10
источник

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

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

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

28
01 нояб. '18 в 16:57
источник

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

[...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.

(основано на максимальных целочисленных значениях), также здесь больше о Typed Arrays):

(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
);
27
05 марта '19 в 8:52
источник

Итоговый отчет. 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()]
25
19 февр. '16 в 18:50
источник

В 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")
17
29 марта '16 в 20:30
источник
for(var i,a=[i=0];i<10;a[i++]=i);

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

13
23 дек. '16 в 2:39
источник

Использование новых методов Array и => функциональный синтаксис из стандарта ES6 (только Firefox на момент написания).

Заполняя отверстия с помощью undefined:

Array(N).fill().map((_, i) => i + 1);

Array.from превращает "дырки" в undefined, поэтому Array.map работает так, как ожидалось:

Array.from(Array(5)).map((_, i) => i + 1)
13
11 нояб. '14 в 17:50
источник

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

const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]

который можно использовать таким образом:

gen(4) // [0,1,2,3]

Приятная вещь в этом - вам не просто нужно увеличивать... Чтобы вдохнуть в ответ ответ от @igor-shubin, вы могли бы легко создать массив рандомов:

const gen = N => [...(function*(){let i=0;
  while(i++<N) yield Math.random()
})()]

И чем-то longy оперативно дорого, например:

const slow = N => new Array(N).join().split(',').map((e,i)=>i*5)
// [0,5,10,15,...]

вы могли бы сделать:

const fast = N => [...(function*(){let i=0;while(i++<N)yield i*5})()]
9
25 апр. '16 в 0:13
источник

Немного проще, чем строковый вариант:

// create range by N
Array(N).join(0).split(0);

// create a range starting with 0 as the value
Array(7).join(0).split(0).map((v, i) => i + 1) // [1, 2, 3, 4, 5, 6, 7]

Обновление (04.01.2008): Обновлено для точного ответа на вопрос OP. Спасибо @lessless за это!

9
22 янв. '15 в 3:36
источник

Итерируемая версия с использованием функции генератора, которая не модифицирует Number.prototype.

function sequence(max, step = 1) {
  return {
    [Symbol.iterator]: function* () {
      for (let i = 1; i <= max; i += step) yield i
    }
  }
}

console.log([...sequence(10)])
8
29 мая '17 в 0:31
источник

Попробуйте следующее:

var foo = [1, 2, 3, 4, 5];

Если вы используете CoffeeScript, вы можете создать диапазон, выполнив следующие действия:

var foo = [1..5]; 

В противном случае, если вы используете ванильный JavaScript, вам нужно будет использовать цикл, если вы хотите инициализировать массив до переменной длины.

8
19 сент. '10 в 20:35
источник

Вы можете использовать генератор функций или выражение функции *. Здесь [ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function ] И ссылка на ссылку генератора функций на [ https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Statement/function ].

let a = 1, b = 10;

function* range(a, b) { for (var я = a; я <= b; ++i) yield i; }

Array.from(range(a, b)); //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

[...range(a, b)] //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

7
20 сент. '16 в 9:56
источник

Использование ES6

const generateArray = n => [...Array(n)].map((_, index) => index + 1);
7
10 февр. '16 в 5:18
источник

Следующая функция возвращает массив, заполненный числами:

var createArrayOfNumbers = function (n) {
    return Array.apply(null, new Array(n)).map(function (empty, index) {
        return index;
    });
};

Обратите внимание, что массив, созданный с помощью конструктора массива, состоит из отверстий, поэтому он не может быть перемещен с помощью функций массива, таких как map. Следовательно, используя функцию Array.apply.

7
14 сент. '13 в 12:39
источник

Еще одна версия ES6.

Используя Array.from второй необязательный аргумент:

Array.from(arrayLike [, mapFn [, thisArg]])

Мы можем построить нумерованный массив из пустых позиций Array(10):

Array.from(Array(10), (_, i) => i)

var arr = Array.from(Array(10), (_, i) => i);
document.write(arr);
7
09 апр. '17 в 1:40
источник

Object.keys(Array.apply(0, Array(3))).map(Number)

Возвращает [0, 1, 2]. Очень похоже на Игорь Шубин отличный ответ, но с чуть меньшим количеством обмана (и один символ дольше).

Пояснение:

  • Array(3) // [undefined × 3] Создать массив длины n = 3. К сожалению, этот массив почти бесполезен для нас, поэтому мы должны...
  • Array.apply(0,Array(3)) // [undefined, undefined, undefined] сделать массив итерабельным. Примечание: null более распространено в качестве применения первого аргумента, но 0 короче.
  • Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2'] затем получить ключи массива (работает, потому что массивы типа type представляют собой объект с индексами для ключей.
  • Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2] и сопоставить клавиши, преобразуя строки в числа.
7
10 февр. '16 в 4:38
источник
  • 1
  • 2

Посмотрите другие вопросы по меткам или Задайте вопрос