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

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

var foo = [];

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

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

Ответы [ 56 ]

2 голосов
/ 24 марта 2017
function arrGen(n) {
  var a = Array(n)
  while (n--) a[n] = n
  return a
}
// arrGen(10) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2 голосов
/ 20 сентября 2010

Просто для удовольствия, я хотел построить из ответ Яна Генри .

Конечно var array = new Array(N); даст вам массив размером N, но ключи и значения будут идентичны .... затем, чтобы сократить массив до размера M, используйте array.length = M .... но для некоторой дополнительной функциональности попробуйте:

function range()
{
    // This function takes optional arguments:
    // start, end, increment
    //    start may be larger or smaller than end
    // Example:  range(null, null, 2);

    var array = []; // Create empty array

      // Get arguments or set default values:
    var start = (arguments[0] ? arguments[0] : 0);
    var end   = (arguments[1] ? arguments[1] : 9);
      // If start == end return array of size 1
    if (start == end) { array.push(start); return array; }
    var inc   = (arguments[2] ? Math.abs(arguments[2]) : 1);

    inc *= (start > end ? -1 : 1); // Figure out which direction to increment.

      // Loop ending condition depends on relative sizes of start and end
    for (var i = start; (start < end ? i <= end : i >= end) ; i += inc)
        array.push(i);

    return array;
}

var foo = range(1, -100, 8.5)

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

Выводвыше:

1 - это элемент: 1 из 12
-7,5 - это элемент: 2 из 12
-16 - это элемент: 3 из 12
-24,5 - это элемент: 412
-33 - это предмет: 5 из 12
-41,5 - это предмет: 6 из 12
-50 - это предмет: 7 из 12
-58,5 - это предмет: 8 из 12
-67 - это предмет: 9 из 12
-75,5 - это предмет: 10 из 12
-84 - это предмет: 11 из 12
-92,5 - это предмет: 12 из 12

Пример jsFiddle

Эта функция использует автоматически сгенерированный массив arguments.

Функция создает массив, заполненный значениями, начинающимися с start и заканчивающимися end с приращениями размера increment, где

range(start, end, increment);

Каждое значение имеет значение по умолчанию, и знак приращения не имеет значения, поскольку направление приращения зависит от относительных размеров начала и конца.

2 голосов
/ 25 февраля 2018

// A solution where you do not allocate a N sized array (ES6, with some flow annotation):
function* zeroToN(N /* : number */)/* : Generator<number, void, empty> */ {
  for (let n = 0; n <= N; n += 1) yield n;
}

// With this generation, you can have your array
console.log([...zeroToN(10-1)])

// but let's define a helper iterator function
function mapIterator(iterator, mapping) {
  const arr = [];
  for (let result = iterator.next(); !result.done; result = iterator.next()) {
    arr.push(mapping(result.value));
  }
  return arr;
}

// now you have a map function, without allocating that 0...N-1 array

console.log(mapIterator(zeroToN(10-1), n => n*n));
2 голосов
/ 16 декабря 2017

ES5 версия, неэффективная, но, возможно, самая короткая, это выражение , а не какой-то оператор , где переменная заполнена, напримерfor петля:

(Array(N)+'').split(',').map(function(d,i){return i})
2 голосов
/ 31 марта 2016

Наименьшее количество кодов, которые я мог бы произвести:

for(foo=[x=100]; x; foo[x-1]=x--);
console.log(foo);
1 голос
/ 30 марта 2019

ES6 решение с использованием рекурсии.Отличается от всех других решений

const range = (n, A = []) => (n === 1) ? [n, ...A] : range(n - 1, [n, ...A]);


console.log(range(5));
1 голос
/ 29 марта 2017

Ну, простой, но важный вопрос.Функциональному JS определенно не хватает универсального метода развертывания в объекте Array, поскольку нам может потребоваться создать массив числовых элементов не только простого [1,2,3,...,111], но и ряда, являющегося результатом функции, может быть как x => x*2 вместо x => x

В настоящее время для выполнения этой работы мы должны полагаться на метод Array.prototype.map().Однако для использования Array.prototype.map() нам нужно заранее знать размер массива.Ну, все же .. если мы не знаем размер, то мы можем использовать Array.prototype.reduce(), но Array.prototype.reduce() предназначен для уменьшения (складывания), а не разворачивания вправо ..?

Так что, очевидно, нам нужен Array.unfold() инструмент в функционале JS.Это то, что мы можем просто реализовать сами, например:

Array.unfold = function(p,f,t,s){
  var res = [],
   runner = v =>  p(v,res.length-1,res) ? [] : (res.push(f(v)),runner(t(v)), res);
  return runner(s);
};

Arrays.unfold(p,f,t,v) принимает 4 аргумента.

  • p Это функция, которая определяетгде остановитьсяФункция p принимает 3 аргумента, как это делают многие функторы массива.Значение, индекс и текущий результирующий массив.Он должен возвращать логическое значение.Когда он возвращает true, рекурсивная итерация останавливается.
  • f Эта функция возвращает функциональное значение следующих элементов.
  • t Эта функция возвращает следующий аргумент для подачи в f в следующем повороте.
  • s Это начальное значение, которое будет использоваться для расчета удобного местас индексом 0 на f.

Так что, если мы намереваемся создать массив, заполненный серией, такой как 1,4,9,16,25 ... n ^ 2, мы можем просто сделать как.

Array.unfold = function(p,f,t,s){
  var res = [],
   runner = v =>  p(v,res.length-1,res) ? [] : (res.push(f(v)),runner(t(v)), res);
  return runner(s);
};

var myArr = Array.unfold((_,i) => i >= 9, x => Math.pow(x,2), x => x+1, 1);
console.log(myArr);
1 голос
/ 16 мая 2019

Вот сводка (запустится в консоли):

// setup:
var n = 10000000;
function* rangeIter(a, b) {
    for (let i = a; i <= b; ++i) yield i;
}
function range(n) { 
    let a = []
    for (; n--; a[n] = n);
    return a;
}
function sequence(max, step = 1) {
    return {
        [Symbol.iterator]: function* () {
            for (let i = 1; i <= max; i += step) yield i
        }
    }
}

var t0, t1, arr;
// tests
t0 = performance.now();
arr = Array.from({ length: n }, (a, i) => 1)
t1 = performance.now();
console.log("Array.from({ length: n }, (a, i) => 1) Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = range(n);
t1 = performance.now();
console.log("range(n) Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = Array.from(rangeIter(0, n));
t1 = performance.now();
console.log("Array.from(rangeIter(0, n)) Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = [...rangeIter(0, n)];
t1 = performance.now();
console.log("[...rangeIter(0, n)] Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = Array.from(sequence(n));
t1 = performance.now();
console.log("Array.from(sequence(n)) Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = [...sequence(n)];
t1 = performance.now();
console.log("[...sequence(n)] Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = Array(n).fill(0).map(Number.call, Number);
t1 = performance.now();
console.log("Array(n).fill(0).map(Number.call, Number) Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = Array.from(Array(n).keys());
t1 = performance.now();
console.log("Array.from(Array(n).keys()) Took " + (t1 - t0) + " milliseconds.");

t0 = performance.now();
arr = [...Array(n).keys()];
t1 = performance.now();
console.log("[...Array(n).keys()] Took " + (t1 - t0) + " milliseconds.");

Самый быстрый - Array (n) .fill (0) .map (Number.call, Number), второй - [... Array (n) .keys ()]

Но способ «... rangeIter» довольно удобен (может быть встроен), быстрый и более мощный

1 голос
/ 12 июня 2014

для получения массива с n случайными числами между min, max (хотя и не уникальным)

0 голосов
/ 18 мая 2017

для меня это более полезная утилита:

/**
 * create an array filled with integer numbers from base to length
 * @param {number} from
 * @param {number} to
 * @param {number} increment
 * @param {Array} exclude
 * @return {Array}
 */
export const count = (from = 0, to = 1, increment = 1, exclude = []) => {
  const array = [];
  for (let i = from; i <= to; i += increment) !exclude.includes(i) && array.push(i);
  return array;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...