Я ищу любые альтернативы ниже для создания массива JavaScript, содержащего от 1 до N, где N известно только во время выполнения.
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
Мне кажется, что должен быть способ сделать это без петли.
javascript
arrays
Godders
источник
источник
1 ... N
?Ответы:
Если я получу то, что вам нужно, вам понадобится массив чисел,
1..n
который вы сможете потом просмотреть.Если это все, что вам нужно, вы можете сделать это вместо этого?
затем, когда вы хотите использовать его ... (без оптимизации, например)
например, если вам не нужно ничего хранить в массиве, вам просто нужен контейнер правильной длины, который вы можете перебирать ... это может быть проще.
Смотрите это в действии здесь: http://jsfiddle.net/3kcvm/
источник
var n = 45;
а затем цикл из1..n
будет делать.foo.length = M
--- Информация об обрезке теряется. Посмотрите это в действии ==> jsfiddle.net/ACMXpvar n = 45;
.new Array(45);
это не «создает массив из 45 элементов» (в том же значении, что[undefined,undefined,..undefined]
и). Это скорее "создает пустой массив с длиной = 45" ([undefined x 45]
), так же, какvar foo = []; foo.length=45;
. Именно поэтомуforEach
иmap
не будет применяться в этом случае.В ES6 используются методы Array from () и keys () .
Укороченная версия с использованием оператора распространения .
источник
map
с массивом, чтобы скорректировать значения ([...Array(10).keys()].map(x => x++);
), чтобы начать с 1map(x => x++)
вmap(x => ++x)
связи с приращением старшинства происходит после возвращения значения :)map
когда можно простоslice
?[...Array(N+1).keys()].slice(1)
keys
и только 1 карту ->Array.from(Array(10)).map((e,i)=>i+1)
from
Array.from(Array(10), (e,i)=>i+1)
Вы можете сделать это:
или со случайными значениями:
объяснение
Во-первых, обратите внимание, что
Number.call(undefined, N)
это эквивалентноNumber(N)
, который просто возвращаетN
. Мы будем использовать этот факт позже.Array.apply(null, [undefined, undefined, undefined])
эквивалентноArray(undefined, undefined, undefined)
, который создает массив из трех элементов и присваиваетundefined
каждому элементу.Как вы можете обобщить это на N элементов? Посмотрим, как
Array()
работает, что-то вроде этого:Начиная с ECMAScript 5 ,
Function.prototype.apply(thisArg, argsArray)
также принимает массивоподобный объект типа утки в качестве второго параметра. Если мы вызовемArray.apply(null, { length: N })
, то он выполнитТеперь у нас есть 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 элементов с неопределенными элементами. Разница заключается в том, что в первом выражении каждый элемент явно установлен на неопределенное значение, тогда как в последнем каждый элемент никогда не задавался. Согласно документации.map()
:Следовательно,
Array(N)
недостаточно;Array(N).map(Number.call, Number)
приведет неинициализированный массив длиной N .Совместимость
Поскольку этот метод основан на поведении,
Function.prototype.apply()
указанном в ECMAScript 5, он не будет работать в браузерах до ECMAScript 5, таких как Chrome 14 и Internet Explorer 9.источник
Function.prototype.call
первый параметр являетсяthis
объектом, отображаемым непосредственно черезArray.prototype.map
параметр итератора, имеет определенный блеск.map
моему, о неназначенных ценностях. Другая версия (и, возможно, немного яснее, хотя и дольше):Array.apply(null, { length: N }).map(function(element, index) { return index; })
Array.apply(null, new Array(N)).map(function(_,i) { return i; })
или, в случае функций es6 и стрелок, еще короче:Array.apply(null, new Array(N)).map((_,i) => i)
Несколько способов использования ES6
Использование оператора распространения (
...
) и метода ключейЗаливка / Карта
Array.from
Array. От и
{ length: N }
взломатьПримечание об обобщенной форме
Все формы могут выдавать массивы инициализируются в значительной степени любых требуемых значения, изменяя
i+1
для выражения требуемого (напримерi*2
,-i
,1+i*2
,i%2
и т.д.). Если выражение может быть выражено некоторой функцией,f
тогда первая форма становится простоПримеры:
Поскольку массив инициализируется с
undefined
в каждой позиции, значениеv
будетundefined
Пример демонстрации всех форм
Показать фрагмент кода
Более общий пример с пользовательской функцией инициализатора,
f
т.е.или даже проще
Показать фрагмент кода
источник
k++
, используйте++k
.Массивы изначально управляют своей длиной. По мере их прохождения их индексы могут храниться в памяти и ссылаться в этой точке. Если необходимо знать случайный индекс,
indexOf
метод может быть использован.Тем не менее, для ваших нужд вы можете просто объявить массив определенного размера:
ES6
Распространение
Использование оператора распространения (
...
) иkeys
метода позволяет вам создать временный массив размера N для создания индексов, а затем новый массив, который можно назначить вашей переменной:Заливка / Карта
Вы можете сначала создать нужный вам размер массива, заполнить его неопределенным, а затем создать новый массив с помощью
map
, который устанавливает каждый элемент в индекс.Array.from
Это должно быть инициализация до длины размера N и заполнение массива за один проход.
Вместо комментариев и путаницы, если вы действительно хотите получить значения из 1..N в приведенных выше примерах, есть несколько вариантов:
++i
).в случаях, когда индекс не используется - и, возможно, более эффективный способ - это создать свой массив, но сделать N равным N + 1, а затем сдвинуться вперед.
Итак, если вы хотите 100 номеров:
источник
В ES6 вы можете сделать:
Array(N).fill().map((e,i)=>i+1);
http://jsbin.com/molabiluwa/edit?js,console
Edit: Изменен
Array(45)
вArray(N)
виду того что вы обновили вопрос.источник
.join.split
версии - но я до сих пор считаю , что скромный цикл лучше.map
, скоро станет стандартом для таких вещей.const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
.fill()
это нужно. Я вижу, что это когда я тестирую на узле repl, но с тех порArray(1)[0] === undefined
, какая разница в вызове fill () вArray(1).fill(undefined)
make?Используйте очень популярный метод Underscore _.range
источник
Потом позвонил
В Javascript нет встроенного способа сделать это, но это совершенно допустимая служебная функция, которую нужно создать, если вам нужно сделать это более одного раза.
Изменить: На мой взгляд, следующая функция является лучшим диапазоном. Может быть, только потому, что я предвзято относится к LINQ, но я думаю, что это более полезно в большинстве случаев. Ваш пробег может варьироваться.
источник
Array
вместо того ,Array.prototype
так как нет никакой причины (это может даже считать довольно тупой) , чтобы этот метод на каждом массиве.Array.range(1, 5)
было бы, вероятно, более подходящим, но есть что-то классное в написании[].range(1, 5)
.foo = [1, 2, 3]; bar = foo.range(0, 10);
. Но это просто ... сбивает с толку.bar = Array.range(0, 10)
намного яснее и понятнее. Диапазон не имеет ничего общего с экземпляром, поэтому нет причин делать его методом экземпляра.самый быстрый способ заполнить
Array
v8:результат будет:
[0, 1, 2, 3, 4]
источник
На этот вопрос есть много сложных ответов, но простая однострочная:
Кроме того, хотя вышеприведенный текст является коротким (и аккуратным) для написания, я думаю, что следующий текст немного быстрее (для максимальной длины:
127, Int8,
255, Uint8,
32,767, Int16,
65 535, Uint16,
2,147,483,647, Int32,
4,294,967,295, Uint32.
(основано на максимальных целочисленных значениях ), также здесь больше о Typed Arrays ):
Хотя это решение также не является идеальным, поскольку оно создает два массива и использует дополнительное объявление переменной «$» (не уверен, что это можно обойти, используя этот метод). Я думаю, что следующее решение - абсолютно быстрый способ сделать это:
В любое время после выполнения этого утверждения вы можете просто использовать переменную «arr» в текущей области видимости;
Если вы хотите сделать из него простую функцию (с некоторой базовой проверкой):
Итак, с вышеуказанной функцией вышеупомянутая супер-медленная «простая однострочная» становится супер-быстрой, даже более короткой:
источник
fill
методом:Array(255).fill(0,0,255)
Вы можете использовать это:
например
создаст следующий массив:
источник
new Array(10).join().split(',').map(function() {return ++arguments[1]});
?join
, один разsplit
и один раз для того, что вы на самом деле хотите сделать) просто нехорошо - я знаю, что они, похоже, потеряли популярность по какой-то причине, но было бы гораздо лучше просто использовать старый добрый цикл !ES6 это сделает свое дело:
проверить результат:
источник
[...Array(N + 1).keys()].slice(1)
даст 1..N[...Array(N + 1).keys()]
этот код возвращает пустой массив, но только в рабочем режиме, используя режим разработки, работает..keys()
Ответ был уже дан лет назад и имеет 500+ upvotes. Что ваш ответ добавляет к этому?Если вы используете d3.js в своем приложении, как и я, D3 предоставит вспомогательную функцию, которая сделает это за вас.
Таким образом, чтобы получить массив от 0 до 4, это так же просто, как:
и получить массив от 1 до 5, как вы запрашивали:
Проверьте этот учебник для получения дополнительной информации.
источник
Использование оператора спреда ES2015 / ES6
источник
i + 1
будет иметь больше смысла, чем++i
.Это, вероятно, самый быстрый способ генерировать массив чисел
самый короткий
В линию
Если вы хотите начать с 1
Хотите функцию?
ПОЧЕМУ?
while
самая быстрая петляПрямая настройка быстрее, чем
push
[]
быстрее чемnew Array(10)
это коротко ... посмотри первый код. затем посмотрите на все остальные функции здесь.
Если вы хотите не может жить без для
или
источник
console.time()
интуицию, но для доказательства вам нужен jsperf.com, и он показывает результаты кроссбраузерного просмотра от других людей (различное оборудование и т. Д.)var a=[],b=N;while(b--){a[b]=a+1};
Если вы используете lodash, вы можете использовать _.range :
Примеры:
источник
Новый способ заполнения
Array
:результат будет:
[0, 1, 2, 3, 4]
источник
с ES6 вы можете сделать:
источник
map
иforEach
будут работать.Итоговый итоговый отчет. Drrruummm Rolll -
Это самый короткий код для генерации массива размера N (здесь 10) без использования ES6 . Версия Cocco выше близка, но не самая короткая.
Но бесспорным победителем этого гольф-кода (соревнования по решению конкретной проблемы в наименьшем количестве байтов исходного кода) является Нико Руотсалайнен . Использование Array Constructor и оператора распространения ES6 . (Большая часть синтаксиса ES6 является допустимым typeScript, но следующее - нет. Поэтому будьте осторожны при его использовании)
источник
a
. Цикл должен бытьfor(var a=[];n--;a[n]=n+1)
В ES6 есть другой способ, использующий Array.from, который принимает 2 аргумента, первый - это arrayLike (в данном случае это объект со
length
свойством), а второй - это функция отображения (в этом случае мы сопоставляем элемент с его индексом).это короче и может использоваться для других последовательностей, таких как генерация четных чисел
Кроме того, это имеет лучшую производительность, чем большинство других способов, потому что он проходит только один раз по массиву. Проверьте фрагмент для некоторых сравнений
источник
Array.from({length:N}, (v,i) => i+1)
Использование новых методов Array и
=>
синтаксиса функций из стандарта ES6 (только Firefox на момент написания).Заполняя отверстия
undefined
:Array.from
превращает «дыры» вundefined
такArray.map
работает, как и ожидалось:источник
Array.from({length: N}, (v, k) => k)
.Array.prototype.map.call
, например, для NodeLists, возвращаемых изdocument.querySelectorAll
. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…Array.from
что превращает разреженные значения в неопределенные. СкорееArray(5)
вызывается как объект аргументов, который в свою очередь интерпретирует разреженные значения как неопределенные значения :)источник
[...Array(9)].map((_, i) => i)
а = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
источник
В ES6:
ES5:
источник
Просто еще одна версия ES6 .
Используя
Array.from
второй необязательный аргумент:Мы можем построить нумерованный массив из пустых
Array(10)
позиций:источник
[...Array(11).keys()].slice(1)
.Похоже, что единственной разновидностью, которой нет в этом довольно полном списке ответов, является вариант с генератором; так, чтобы исправить это:
который можно использовать таким образом:
Хорошая вещь в этом заключается в том, что вам не нужно просто увеличивать ... Чтобы черпать вдохновение из ответа, который дал @ igor-shubin, вы можете очень легко создать массив случайностей:
И вместо того, чтобы что-то
длительноеэксплуатационно дорого, как:Вы могли бы вместо этого сделать:
источник
Вы можете использовать Array fill и map из Es6; так же, как некоторые люди предложили в ответах на этот вопрос. Ниже приведено несколько примеров:
Я предпочитаю это, потому что нахожу это прямым и легким.
источник
Источник: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
источник
Использование ES6
источник
Array.from(Array(n))
если оператор распространения не поддерживается.map
MDN : «Он не вызывается для отсутствующих элементов массива (то есть индексов, которые никогда не были установлены, которые имеют были удалены или которым никогда не было присвоено значение). "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]
сделать массив повторяемым. Примечание: ноль более распространен, так как первый аргумент применяется, но короче 0.Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2']
затем получить ключи массива (работает, потому что массивы typeof это массив с индексами для ключей.Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2]
и сопоставьте ключи, преобразовав строки в числа.источник