Estoy buscando alternativas a las siguientes 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 manera de hacer esto sin el bucle.
javascript
arrays
Godders
fuente
fuente
1 ... N
?Respuestas:
Si obtengo lo que buscas, quieres una matriz de números
1..n
que luego puedas recorrer.Si esto es todo lo que necesitas, ¿puedes hacer esto en su lugar?
entonces cuando quieras usarlo ... (no optimizado, solo por ejemplo)
por ejemplo, si no necesita almacenar nada en la matriz, solo necesita un contenedor de la longitud correcta sobre el que pueda iterar ... esto podría ser más fácil.
Véalo en acción aquí: http://jsfiddle.net/3kcvm/
fuente
var n = 45;
y luego bucle1..n
sería suficiente.foo.length = M
--- La información de corte se pierde. Véalovar n = 45;
.new Array(45);
no "crea una matriz de 45 elementos" (en el mismo significado que lo[undefined,undefined,..undefined]
hace). Más bien "crea una matriz vacía con longitud = 45" ([undefined x 45]
), igual quevar foo = []; foo.length=45;
. Por esoforEach
, ymap
no se aplicará en este caso.En ES6 utilizando los métodos Array from () y keys () .
Versión más corta con operador de propagación .
fuente
map
a la matriz para ajustar los valores ([...Array(10).keys()].map(x => x++);
) para comenzar en 1map(x => x++)
amap(x => ++x)
debido a que el incremento de precedencia ocurre después del retorno del valor :)map
cuando puedes simplementeslice
?[...Array(N+1).keys()].slice(1)
keys
y solo 1 mapa ->Array.from(Array(10)).map((e,i)=>i+1)
from
Array.from(Array(10), (e,i)=>i+1)
Puedes hacerlo:
o con valores aleatorios:
Explicación
Primero, tenga en cuenta que
Number.call(undefined, N)
es equivalente aNumber(N)
, que simplemente regresaN
. Usaremos ese hecho más tarde.Array.apply(null, [undefined, undefined, undefined])
es equivalente aArray(undefined, undefined, undefined)
, que produce una matriz de tres elementos y se asignaundefined
a cada elemento.¿Cómo puedes generalizar eso a N elementos? Considere cómo
Array()
funciona, que es algo como esto:Desde ECMAScript 5 ,
Function.prototype.apply(thisArg, argsArray)
también acepta un objeto tipo matriz tipo pato como su segundo parámetro. Si invocamosArray.apply(null, { length: N })
, se ejecutaráAhora tenemos una matriz de elementos N , con cada elemento establecido en
undefined
. Cuando lo invoquemos.map(callback, thisArg)
, cada elemento se establecerá en el resultado decallback.call(thisArg, element, index, array)
. Por[undefined, undefined, …, undefined].map(Number.call, Number)
lo tanto, correlacionaría cada elemento con(Number.call).call(Number, undefined, index, array)
, que es lo mismoNumber.call(undefined, index, array)
que, como observamos anteriormente, se evalúa comoindex
. Eso completa la matriz cuyos elementos son los mismos que su índice.¿Por qué pasar por la molestia de en
Array.apply(null, {length: N})
lugar de soloArray(N)
? Después de todo, ambas expresiones resultarían en una matriz de elementos N de elementos indefinidos. La diferencia es que en la primera expresión, cada elemento se establece explícitamente en indefinido, mientras que en la última, cada elemento nunca se estableció. De acuerdo con la documentación de.map()
:Por lo tanto,
Array(N)
es insuficiente;Array(N).map(Number.call, Number)
resultaría en una matriz sin inicializar de longitud N .Compatibilidad
Dado que esta técnica se basa en el comportamiento
Function.prototype.apply()
especificado en ECMAScript 5, no funcionará en navegadores anteriores a ECMAScript 5 como Chrome 14 e Internet Explorer 9.fuente
Function.prototype.call
el primer parámetro es elthis
objeto a mapear directamente sobreArray.prototype.map
el parámetro iterador tiene un cierto brillo.map
valores no asignados, en mi opinión. Otra versión (y posiblemente un poco más clara, aunque más larga) es:Array.apply(null, { length: N }).map(function(element, index) { return index; })
Array.apply(null, new Array(N)).map(function(_,i) { return i; })
o, en el caso de es6 y funciones de flecha, aún más corto:Array.apply(null, new Array(N)).map((_,i) => i)
Múltiples formas de usar ES6
Usando el operador spread (
...
) y el método de teclasRelleno / Mapa
Array.from
Array.from y
{ length: N }
piratearNota sobre forma generalizada
Todas las formas anteriores matrices pueden producir inicializados a los valores casi cualquier deseadas cambiando
i+1
a la expresión requerida (por ejemploi*2
,-i
,1+i*2
,i%2
y etc). Si la expresión puede ser expresada por alguna función,f
entonces la primera forma se vuelve simplementeEjemplos:
Como la matriz se inicializa con
undefined
cada posición, el valor dev
seráundefined
Ejemplo mostrando todos los formularios
Mostrar fragmento de código
Ejemplo más genérico con función de inicializador personalizado,
f
es deciro incluso más simple
Mostrar fragmento de código
fuente
k++
, use++k
.Las matrices administran de manera innata sus longitudes. A medida que se atraviesan, sus índices pueden mantenerse en la memoria y referenciarse en ese punto. Si se necesita conocer un índice aleatorio,
indexOf
se puede usar el método.Dicho esto, para sus necesidades, es posible que desee declarar una matriz de cierto tamaño:
ES6
Propagar
Al utilizar el operador de propagación (
...
) y elkeys
método, le permite crear una matriz temporal de tamaño N para producir los índices, y luego una nueva matriz que puede asignarse a su variable:Relleno / 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.Array.from
Esto debería inicializarse a una longitud de tamaño N y llenar la matriz en una pasada.
En lugar de los comentarios y la confusión, si realmente desea capturar los valores de 1..N en los ejemplos anteriores, hay un par de opciones:
++i
).en los casos en que no se usa el índice, y posiblemente una forma más eficiente, es crear su matriz pero hacer que N represente N + 1, luego desplazarse hacia adelante.
Entonces, si deseas 100 números:
fuente
En ES6 puedes hacer:
Array(N).fill().map((e,i)=>i+1);
http://jsbin.com/molabiluwa/edit?js,console
Editar: cambiado
Array(45)
aArray(N)
desde que actualizó la pregunta.fuente
.join.split
versión desagradable , pero sigo pensando que el bucle humilde es mejor.map
que pronto se convertirá en un estándar para cosas como esta.const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
.fill()
es necesario. Veo que es cuando pruebo las respuestas del nodo, pero desde entoncesArray(1)[0] === undefined
, ¿qué diferencia hace la llamada a fill ()Array(1).fill(undefined)
?Utilice el método de subrayado muy popular _.range
fuente
Luego llamado por
No hay una forma integrada de hacer esto en Javascript, pero es una función de utilidad perfectamente válida para crear si necesita hacerlo más de una vez.
Editar: en mi opinión, la siguiente es una mejor función de rango. Quizás solo porque estoy sesgado por LINQ, pero creo que es más útil en más casos. Su experiencia puede ser diferente.
fuente
Array
lugar deArray.prototype
que no haya ninguna razón (incluso podría considerarse bastante tonto) para tener este método en cada matriz.Array.range(1, 5)
probablemente sería más apropiado, pero hay algo genial en escribir[].range(1, 5)
.foo = [1, 2, 3]; bar = foo.range(0, 10);
. Pero eso es solo ... confuso.bar = Array.range(0, 10)
Es mucho más claro y explícito. El rango no tiene nada que ver con la instancia, por lo que no hay razón para convertirlo en un método de instancia.La forma más rápida de completar un
Array
v8 es:el resultado será:
[0, 1, 2, 3, 4]
fuente
Esta pregunta tiene muchas respuestas complicadas, pero una frase simple:
Además, aunque lo anterior es corto (y ordenado) para escribir, creo que lo siguiente es un poco más rápido (para una longitud máxima de:
127, Int8,
255, Uint8,
32,767, Int16,
65.535, Uint16,
2,147,483,647, Int32,
4.294.967.295, Uint32.
(basado en los valores enteros máximos ), también aquí hay más sobre matrices escritas ):
Aunque esta solución tampoco es tan ideal, ya que crea dos matrices y usa la declaración de variable adicional "$" (no estoy seguro de ninguna forma de evitar eso usando este método). Creo que la siguiente solución es la forma más rápida posible de hacer esto:
En cualquier momento después de que se haga esta declaración, puede simplemente usar la variable "arr" en el alcance actual;
Si desea hacer una función simple (con alguna verificación básica):
entonces, con la función anterior, el "one-liner simple" súper lento anterior se convierte en súper rápido, incluso más corto
fuente
fill
método:Array(255).fill(0,0,255)
Puedes usar esto:
por ejemplo
creará la siguiente matriz:
fuente
new Array(10).join().split(',').map(function() {return ++arguments[1]});
?join
, unasplit
vez y una vez por lo que realmente quieres hacer) simplemente no es agradable: sé que parecen haber caído en desgracia por alguna razón, ¡pero sería mucho mejor simplemente usar un buen bucle antiguo !ES6 esto hará el truco:
mira el resultado:
fuente
[...Array(N + 1).keys()].slice(1)
rendirá 1..N[...Array(N + 1).keys()]
este código devuelve una matriz vacía, pero solo en el modo de producción, usando el modo de desarrollo funciona..keys()
respuesta ya se dio hace años y tiene más de 500 votos a favor. ¿Qué le agrega su respuesta?Si está utilizando d3.js en su aplicación como yo, D3 proporciona una función auxiliar que lo hace por usted.
Entonces, para obtener una matriz de 0 a 4, es tan fácil como:
y para obtener una matriz de 1 a 5, como estaba solicitando:
Mira este tutorial para más información.
fuente
Uso del operador de propagación ES2015 / ES6
fuente
i + 1
tendría más sentido que++i
.Esta es probablemente la forma más rápida de generar una serie de números.
Más corto
En línea
Si quieres comenzar desde 1
¿Quieres una función?
¿POR QUÉ?
while
es el bucle más rápidoLa configuración directa es más rápida que
push
[]
es más rápido quenew Array(10)
es corto ... mira el primer código. entonces mira todas las otras funciones aquí.
Si te gusta no pueden vivir sin por
o
fuente
console.time()
para tener una intuición, pero para una prueba, necesita jsperf.com Y le muestra los resultados del navegador cruzado de otras personas (hardware diferente, etc.)var a=[],b=N;while(b--){a[b]=a+1};
Si está usando lodash, puede usar _.range :
Ejemplos:
fuente
La nueva forma de llenar
Array
es:el resultado será:
[0, 1, 2, 3, 4]
fuente
con ES6 puedes hacer:
fuente
map
yforEach
trabajarán.Informe final resumido .. Drrruummm Rolll -
Este es el código más corto para generar una matriz de tamaño N (aquí 10) sin usar ES6 . La versión anterior de Cocco es cercana pero no la más corta.
Pero el ganador indiscutible de este Golf de código (competencia para resolver un problema particular en la menor cantidad de bytes de código fuente) es Niko Ruotsalainen . Utilizando Array Constructor y ES6 spread operator . (La mayor parte de la sintaxis de ES6 es typeScript válido, pero el siguiente no lo es. Por lo tanto, sea prudente al usarlo)
fuente
a
. El bucle debería serfor(var a=[];n--;a[n]=n+1)
Hay otra forma en ES6, usando Array.from que toma 2 argumentos, el primero es un arrayLike (en este caso un objeto con
length
propiedad), y el segundo es una función de mapeo (en este caso mapeamos el elemento a su índice)esto es más corto y puede usarse para otras secuencias como generar números pares
Además, tiene un mejor rendimiento que la mayoría de las otras formas porque solo se repite una vez a través de la matriz. Verifique el snippit para algunas comparaciones
fuente
Array.from({length:N}, (v,i) => i+1)
Usando nuevos métodos de matriz y
=>
sintaxis de funciones del estándar ES6 (solo Firefox en el momento de la escritura).Al llenar agujeros con
undefined
:Array.from
convierte "agujeros" enundefined
tanArray.map
funciona como se esperaba:fuente
Array.from({length: N}, (v, k) => k)
.Array.prototype.map.call
, por ejemplo, para las NodeLists devueltasdocument.querySelectorAll
. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…Array.from
que convierte los valores dispersos en indefinidos. Más bienArray(5)
se llama como un objeto de argumentos que a su vez interpreta los valores dispersos como valores indefinidos :)fuente
[...Array(9)].map((_, i) => i)
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
fuente
En ES6:
ES5:
fuente
Solo otra versión ES6 .
Al hacer uso del
Array.from
segundo argumento opcional:Podemos construir la matriz numerada desde las
Array(10)
posiciones vacías :fuente
[...Array(11).keys()].slice(1)
.Parece que el único sabor que no está actualmente en esta lista bastante completa de respuestas es uno con un generador; para remediar eso:
que puede usarse así:
Lo bueno de esto es que no solo tienes que aumentar ... Para inspirarte en la respuesta que dio @ igor-shubin, puedes crear una variedad de randoms muy fácilmente:
Y en lugar de algo
largo,operacionalmente costoso como:en su lugar podrías hacer:
fuente
Puede usar el relleno de matriz y el mapa desde Es6; tal como algunas personas sugirieron en las respuestas que dieron para esta pregunta. A continuación hay algunos ejemplos:
Prefiero esto porque lo encuentro sencillo y sencillo.
fuente
Fuente: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
fuente
Usando ES6
fuente
Array.from(Array(n))
si el operador de propagación no es compatible.map
MDN : "No se requieren elementos faltantes de la matriz (es decir, índices que nunca se han establecido, que tienen eliminado o al que nunca se le ha asignado un valor) ".Object.keys(Array.apply(0, Array(3))).map(Number)
Las devoluciones
[0, 1, 2]
. Muy similar a la excelente respuesta de Igor Shubin , pero con un poco menos de trucos (y un personaje más).Explicación:
Array(3) // [undefined × 3]
Genere una matriz de longitud n = 3. Desafortunadamente, esta matriz es casi inútil para nosotros, así que tenemos que ...Array.apply(0,Array(3)) // [undefined, undefined, undefined]
hacer que la matriz sea iterable. Nota: null es más común que el primer argumento de apply pero 0 es más corto.Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2']
luego obtenga las claves de la matriz (funciona porque las matrices son el tipo de matriz es un objeto con índices para las claves.Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2]
y mapear sobre las teclas, convirtiendo cadenas en números.fuente