Pregunta Crear una matriz de JavaScript que contenga 1 ... N


Estoy buscando alternativas para crear una matriz de JavaScript que contenga de 1 a N, donde N solo se conoce en tiempo de ejecución.

var foo = [];

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

Para mí, parece que debería haber una forma de hacerlo sin el bucle.


593
2017-09-19 17:34


origen


Respuestas:


Si obtengo lo que buscas, quieres una matriz de números 1..n que luego puedes recorrer.

Si esto es todo lo que necesita, ¿puede hacer esto en su lugar?

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

luego cuando quieras usarlo ... (no optimizado, solo por ejemplo)

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

p.ej. si no necesitas almacenar cualquier cosa en la matriz, solo necesitas un contenedor de la longitud correcta sobre la cual puedas iterar ... esto podría ser más fácil.

Véalo en acción aquí: http://jsfiddle.net/3kcvm/


202
2017-09-19 17:54



Puedes hacerlo:

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

resultado: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

o con valores aleatorios:

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

resultado: [0.7082694901619107, 0.9572225909214467, 0.8586748542729765,   0.8653848143294454, 0.008339877473190427, 0.9911756622605026, 0.8133423360995948, 0.8377588465809822, 0.5577575915958732, 0.16363654541783035]

Explicación

Primero, tenga en cuenta que Number.call(undefined, N) es equivalente a Number(N), que simplemente regresa N. Usaremos ese hecho más tarde.

Array.apply(null, [undefined, undefined, undefined]) es equivalente a Array(undefined, undefined, undefined), que produce una matriz de tres elementos y asigna undefined a cada elemento.

¿Cómo puedes generalizar eso para norte ¿elementos? Considera cómo Array() funciona, que dice algo como esto:

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;
}

Desde ECMAScript 5, Function.prototype.apply(thisArg, argsArray) también acepta un objeto parecido a una matriz tipo pato como su segundo parámetro. Si invocamos Array.apply(null, { length: N }), entonces se ejecutará

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

Ahora tenemos un norte-element array, con cada elemento configurado para undefined. Cuando llamamos .map(callback, thisArg) en él, cada elemento se establecerá en el resultado de callback.call(thisArg, element, index, array). Por lo tanto, [undefined, undefined, …, undefined].map(Number.call, Number) asignaría cada elemento a (Number.call).call(Number, undefined, index, array), que es lo mismo que Number.call(undefined, index, array), que, como hemos observado anteriormente, se evalúa como index. Eso completa la matriz cuyos elementos son los mismos que su índice.

¿Por qué pasar por la molestia de Array.apply(null, {length: N}) en lugar de simplemente Array(N)? Después de todo, ambas expresiones resultarían en una norte-elemento de elementos indefinidos. La diferencia es que en la primera expresión, cada elemento es explícitamente conjunto indefinido, mientras que en el último, cada elemento nunca se estableció. De acuerdo con la documentación de .map():

callback se invoca solo para los índices de la matriz que tienen valores asignados; no se invoca para los índices que se han eliminado o para los que nunca se han asignado valores.

Por lo tanto, Array(N) es insuficiente; Array(N).map(Number.call, Number) daría como resultado una matriz no inicializada de longitud norte.

Compatibilidad

Dado que esta técnica se basa en el comportamiento de Function.prototype.apply() especificado en ECMAScript 5, lo hará no trabajo en navegadores anteriores a ECMAScript 5 como Chrome 14 e Internet Explorer 9.


655
2017-11-19 08:33



En ES6 usando matriz de() y llaves() métodos.

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

Versión más corta usando operador de propagación.

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

515
2017-10-26 18:03



Manera simple y breve en ES6:

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

Por lo tanto:

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

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

console.log(
  range(5)
)


165
2017-07-05 21:38



En ES6 puedes hacer:

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

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

Editar: Cambiado Array(45) a Array(N) ya que has actualizado la pregunta


125
2017-12-21 03:18



Usa el muy popular Underscore _.range method

// _.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); // => []

89
2018-06-26 22:05



Sé que su pregunta es pedir llenar una matriz numéricamente, pero no estoy seguro de por qué querría hacer esto.

Las matrices administran innatamente sus longitudes. A medida que se cruzan, sus índices pueden mantenerse en la memoria y referenciarse en ese punto. Si se necesita conocer un índice aleatorio, el indexOf método puede ser utilizado.


Dicho esto, para sus necesidades, tal vez solo quiera declarar una matriz de cierto tamaño:

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

Untado

Haciendo uso del operador de propagación (...) y keys método, le permite crear una matriz temporal de tamaño N para producir los índices, y luego una nueva matriz que se puede asignar a su variable:

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

Rellenar / Mapa

Primero puede crear el tamaño de la matriz que necesita, llenarlo con indefinido y luego crear una nueva matriz usando map, que establece cada elemento en el índice.

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

70
2017-09-19 18:06