tabla - Cree una matriz de JavaScript que contenga 1... N
javascript ejemplos (30)
Object.keys(Array.apply(0, Array(3))).map(Number)
Devuelve [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]
Genera un array de longitud n = 3. Desafortunadamente, este conjunto es casi inútil para nosotros, así que tenemos que ... -
Array.apply(0,Array(3)) // [undefined, undefined, undefined]
hace que el array 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 obtiene 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 mapea sobre las teclas, convirtiendo cadenas en números.
Estoy buscando alternativas al siguiente 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í, siento que debería haber una manera de hacer esto sin el bucle.
Forma simple y breve en ES6 :
Array.from({length: 5}, (v, k) => k+1);
// [1,2,3,4,5]
Así:
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)
)
ES6 esto hará el truco:
[...Array(12).keys()]
Echa un vistazo al resultado:
[...Array(12).keys()].map(number => console.log(number))
En ES6 puedes hacer:
Array(N).fill().map((e,i)=>i+1);
http://jsbin.com/molabiluwa/edit?js,console
Editar: Cambió la Array(45)
a la Array(N)
desde que actualizó la pregunta.
console.log(
Array(45).fill(0).map((e,i)=>i+1)
);
En ES6 utilizando los métodos Array from() y keys() .
Array.from(Array(10).keys())
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Versión más corta utilizando operador extendido .
[...Array(10).keys()]
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Estaba buscando una solución funcional y terminé con:
function numbers(min, max) {
return Array(max-min+2).join().split('','').map(function(e, i) { return min+i; });
}
console.log(numbers(1, 9));
Nota: join().split('','')
transforma la matriz dispersa en una contigua.
Hay otra forma en ES6, usando Array.from que toma 2 argumentos, el primero es un arrayLike (en este caso un objeto con propiedad de length
), y el segundo es una función de mapeo (en este caso mapeamos el elemento a su índice) )
Array.from({length:10}, (v,i) => i)
esto es más corto y se puede usar para otras secuencias como generar números pares
Array.from({length:10}, (v,i) => i*2)
Además, esto tiene mejor rendimiento que la mayoría de las otras formas porque solo se repite una vez a través de la matriz. Compruebe el fragmento para algunas comparaciones
// 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")
Improvisando sobre lo anterior:
var range = function (n) {
return Array(n).join().split('','').map(function(e, i) { return i; });
}
Uno puede obtener las siguientes opciones:
1) Array.init para valorar v
var arrayInitTo = function (n,v) {
return Array(n).join().split('','').map(function() { return v; });
};
2) obtener un rango invertido:
var rangeRev = function (n) {
return Array(n).join().split('','').map(function() { return n--; });
};
La forma más rápida de llenar Array
en v8 es:
[...Array(5)].map((_,i) => i);
el resultado será: [0, 1, 2, 3, 4]
La siguiente función devuelve una matriz llena de números:
var createArrayOfNumbers = function (n) {
return Array.apply(null, new Array(n)).map(function (empty, index) {
return index;
});
};
Tenga en cuenta que una matriz creada con el constructor de matriz consta de orificios, por lo que no se puede atravesar con funciones de matriz como map. Por lo tanto, utilizando la función Array.apply
.
No vi ninguna solución basada en funciones recursivas (y nunca escribí funciones recursivas), así que aquí está mi intento.
Tenga en cuenta que array.push (algo) devuelve la nueva longitud de la matriz:
(a=[]).push(a.push(a.push(0))) // a = [0, 1, 2]
Y con una función recursiva:
var a = (function f(s,e,a,n){return ((n?n:n=s)>e)?a:f(s,e,a?a:a=[],a.push(n)+s)})(start,end) // e.g., start = 1, end = 5
EDIT: otras dos soluciones
var a = Object.keys(new Int8Array(6)).map(Number).slice(1)
y
var a = []
var i=setInterval(function(){a.length===5?clearInterval(i):a.push(a.length+1)})
Parece que el único sabor que actualmente no está en esta lista de respuestas bastante completa es uno que presenta un generador; para remediar eso:
const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
Que se puede utilizar así:
gen(4) // [0,1,2,3]
Lo bueno de esto es que no solo tienes que incrementar ... Para inspirarte en la respuesta que dio @ igor-shubin, puedes crear una gran variedad de randoms muy fácilmente:
const gen = N => [...(function*(){let i=0;
while(i++<N) yield Math.random()
})()]
Y en lugar de algo largo operacionalmente costoso como:
const slow = N => new Array(N).join().split('','').map((e,i)=>i*5)
// [0,5,10,15,...]
en su lugar podrías hacer
const fast = N => [...(function*(){let i=0;while(i++<N)yield i*5})()]
Prueba esto:
var foo = [1, 2, 3, 4, 5];
Si está utilizando CoffeeScript , puede crear un rango haciendo:
var foo = [1..5];
De lo contrario, si está utilizando JavaScript de vainilla, tendrá que usar un bucle si desea inicializar una matriz hasta una longitud variable.
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,99117566ukopovolucopelipolenciavolucinventa, 0,9443851200602626, 01973496060482, 0,8775889809898, 0997759892595259525952495191919202419.png.
Explicación
Primero, tenga en cuenta que Number.call(undefined, N)
es equivalente a Number(N)
, que simplemente devuelve N
Vamos a utilizar 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 a N elementos? Considera cómo funciona Array()
, que es 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 similar a una matriz de tipo pato como su segundo parámetro. Si invocamos Array.apply(null, { length: N })
, se ejecutará
function Array() {
var a = [];
for (var i = 0; i < /* arguments.length = */ N; i++) {
a.push(/* arguments[i] = */ undefined);
}
return a;
}
Ahora tenemos una matriz de elementos N , con cada elemento establecido como undefined
. Cuando llamamos a .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)
cada elemento a (Number.call).call(Number, undefined, index, array)
, que es lo mismo que Number.call(undefined, index, array)
, que, como observamos anteriormente, se evalúa para index
. Eso completa la matriz cuyos elementos son los mismos que su índice.
¿Por qué pasar por el problema de Array.apply(null, {length: N})
lugar de solo Array(N)
? Después de todo, ambas expresiones darían lugar a una matriz de elementos no definidos con un elemento N - N . La diferencia es que en la expresión anterior, cada elemento se establece explícitamente en indefinido, mientras que en la última, cada elemento nunca se estableció. Según 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 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 N.
Compatibilidad
Dado que esta técnica se basa en el comportamiento de Function.prototype.apply()
especificado en ECMAScript 5, no funcionará en los navegadores pre-ECMAScript 5 como Chrome 14 e Internet Explorer 9.
Puedes usar esto:
new Array(/*any number which you want*/)
.join().split('','')
.map(function(item, index){ return ++index;})
por ejemplo
new Array(10)
.join().split('','')
.map(function(item, index){ return ++index;})
creará la siguiente matriz:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Sé que su pregunta está pidiendo rellenar una matriz numéricamente, pero no estoy seguro de por qué querría hacer esto.
Las matrices gestionan de forma innata sus longitudes. A medida que se recorren, sus índices se pueden mantener en la memoria y hacer referencia en ese punto. Si es necesario conocer un índice aleatorio, se puede usar el método indexOf
.
Dicho esto, para sus necesidades puede que desee declarar una matriz de un tamaño determinado:
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
Al utilizar el operador de propagación ( ...
) y el método de las keys
, le permite crear una matriz temporal de tamaño N para generar 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, rellenarla con undefined y luego crear una nueva matriz utilizando map
, que establece cada elemento en el índice.
var foo = Array(N).fill().map((v,i)=>i);
Array.from
Esto debería inicializarse a la longitud del tamaño N y rellenar la matriz en una sola pasada.
Array.from({ length: N }, (v, i) => i)
Si está usando d3.js en su aplicación como lo soy yo, D3 proporciona una función de ayuda que lo hace por usted.
Entonces, para obtener una matriz de 0 a 4, es tan fácil como:
d3.range(5)
[0, 1, 2, 3, 4]
y para obtener una matriz de 1 a 5, como estaba solicitando:
d3.range(1, 5+1)
[1, 2, 3, 4, 5]
Echa un vistazo a este tutorial para más información.
Si está usando lodash, puede usar _.range :
_.range([start=0], end, [step=1])
Crea una matriz de números (positivos y / o negativos) que progresan desde el inicio hasta el final, pero sin incluirlo. Se utiliza un paso de -1 si se especifica un inicio negativo sin un final o paso. Si no se especifica el final, se establece para comenzar con el inicio y luego se establece en 0.
Ejemplos:
_.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);
// ➜ []
Si obtengo lo que buscas, quieres un conjunto 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 quiera usarlo ... (sin optimizar, solo por ejemplo)
for(var i = 0; i < foo.length; i++){
document.write(''Item: '' + (i + 1) + '' of '' + foo.length + ''<br/>'');
}
por ejemplo, si no necesita almacenar nada en la matriz, solo necesita un contenedor de la longitud correcta que pueda repetir ... esto podría ser más fácil.
Véalo en acción aquí: http://jsfiddle.net/3kcvm/
Solo otra versión de ES6 .
Haciendo uso de from() segundo argumento opcional:
Array.from (arrayLike [, mapFn [, thisArg]])
Podemos construir la matriz numerada a partir de las posiciones de la Array(10)
vacías:
Array.from(Array(10), (_, i) => i)
var arr = Array.from(Array(10), (_, i) => i);
document.write(arr);
Un poco más simple que la variante de cadena:
// 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(Number.call, Number); // [0, 1, 2, 3, 4, 5, 6]
Usando ES2015 / ES6 operador extendido
[...Array(10)].map((_, i) => ++i)
console.log([...Array(10)].map((_, i) => ++i))
Uso de nuevos métodos de Array y la sintaxis de la función =>
del estándar ES6 (solo Firefox en el momento de la escritura).
Rellenando agujeros con undefined
:
Array(N).fill().map((_, i) => i + 1);
Array.from
convierte "agujeros" en undefined
por lo que Array.map
funciona como se esperaba:
Array.from(Array(5)).map((_, i) => i + 1)
Utilice el método de subrayado muy popular _.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); // => []
Resumen del informe final ... Drrruummm Rolll -
Este es el código más corto para generar un Array de tamaño N (aquí 10) sin usar ES6 . La versión anterior de es cercana pero no la más corta.
(function(n){for(a=[];n--;a[n]=n+1);return a})(10)
Pero el ganador indiscutible de este Código de golf (competencia para resolver un problema particular en el menor número de bytes del código fuente) es . Usando Array Constructor y ES6 propagación operador . (La mayor parte de la sintaxis de ES6 es un código de tipo válido, pero no lo es el siguiente. Por lo tanto, sea juicioso al usarlo)
[...Array(10).keys()]
Esta es prolly la forma más rápida de generar una serie de números.
El mas corto
var a=[],b=N;while(b--)a[b]=b+1;
En línea
var arr=(function(a,b){while(a--)b[a]=a;return b})(10,[]);
//arr=[0,1,2,3,4,5,6,7,8,9]
Si quieres empezar desde 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]
¿Quieres una función?
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]
¿POR QUÉ?
while
es el bucle más rápidoEl ajuste directo es más rápido que el
push
[]
es más rápido que lanew Array(10)
Es corto ... mira el primer código. entonces mira todas las otras funciones aquí.
Si te gusta no puedes vivir sin para
for(var a=[],b=7;b>0;a[--b]=b+1); //a=[1,2,3,4,5,6,7]
o
for(var a=[],b=7;b--;a[b]=b+1); //a=[1,2,3,4,5,6,7]
nota : apply
, map
, join
- split
.... srsly ??? eso es malditamente lento y compatibilidad ???
Array(8).fill(0).map(Number.call, Number)
Robo de Igors Number.call
truco pero usando fill()
para acortar un poco. Solo funciona con ES6 y superior.
for(var i,a=[i=0];i<10;a[i++]=i);
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
function range(start, end) {
var foo = [];
for (var i = start; i <= end; i++) {
foo.push(i);
}
return foo;
}
Entonces llamado por
var foo = range(1, 5);
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.
Edición: en mi opinión, la siguiente es una mejor función de rango. Tal vez solo porque estoy sesgado por LINQ, pero creo que es más útil en más casos. Su experiencia puede ser diferente.
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;
}