Manera más breve de crear una matriz de enteros de 1..20 en JavaScript

9 minutos de lectura

avatar de usuario
pulmón de arte

¿Cuál sería la forma más breve de crear esta matriz?

var x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
         11, 12, 13, 14, 15, 16, 17, 18, 19, 20];

por ejemplo, un for círculo:

var x = [];
for (var i=1;i<=20;i++) {
  x.push(i);
}

o un while círculo:

var x = [], i = 1, endInt = 20;
while (i <= endInt) {
  x.push(i);
  i++;
}

¿Habría otros ejemplos que serían más breves, en otras palabras, menos código? Estoy pensando en cosas como en Ruby, donde creo que el código equivalente sería tan simple como 1..20. No conozco una sintaxis como esa en JavaScript, pero me pregunto si hay formas más cortas de hacer lo mismo.

ACTUALIZAR: No estaba pensando en eliminar puntos y comas o var para respuestas en la pregunta, pero tengo que admitir que la pregunta implica eso. Tengo más curiosidad por los algoritmos que por los bytes de afeitado. Lo siento si no estaba claro! Además, convertirlo en una función es bastante simple, simplemente abofetea function range(start, end) { /* guts here */ } a su alrededor y estás allí. La pregunta es si existen enfoques novedosos para las “tripas”.

  • ¿Hay alguna razón por la que la brevedad del código sea importante, o es solo un experimento mental?

    – templatetypedef

    9 de junio de 2011 a las 21:27

  • Realmente un experimento mental más que nada. Estaba creando una matriz y pensando en realidad en PHP, donde puedo hacer var $x = range(1, 20);… como, ¿por qué no en JavaScript?

    – artlung

    9 de junio de 2011 a las 21:28

  • ¿Por qué no creas la función? range() en JS y usar eso?

    – svick

    9 junio 2011 a las 21:30

  • los push() El método en realidad no es muy inteligente aquí debido al crecimiento dinámico de la matriz. Si conoce la cantidad de campos de antemano, debe usar una inicialización explícita de tamaño y completar los campos a través de la indexación: x[i-start_i] = i;

    – Martín Hennings

    9 de junio de 2011 a las 21:32

  • No puedo evitar pensar que el comentario de Svicks es la respuesta adecuada. Es JS después de todo.

    – Capitán Jirafa

    9 de junio de 2011 a las 21:35

avatar de usuario
ninjagecko

método favorito

Actualización 13 de septiembre de 2015:

Se me acaba de ocurrir este nuevo método que funciona con navegadores compatibles con el estándar ES6:

> Array(5).fill().map((x,i)=>i)
[0, 1, 2, 3, 4]

Tenga en cuenta que lo anterior hace un poco de trabajo extra (se llena con undefined) pero es relativamente menor en comparación con la aceleración que puede lograr usando un bucle for, y si olvida el .fill puede estar confundido por qué su matriz es misteriosamente [empty x 5]. Puede encapsular lo anterior como una función personalizada o, alternativamente, usar un método algo más intencionado:

> Array.from(Array(5),(x,i)=>i)
[0, 1, 2, 3, 4]

Por supuesto, puede pasar directamente de eso a lo que quiera hacer, como las listas de comprensiones de Python, por ejemplo. [i**2 for i in range(5)]:

> Array.from(Array(5), (_,i)=> i**2)
[0, 1, 4, 9, 16]

… o si quieres complicarte más…:

> Array.from(Array(5), (_,i)=> {
    const R = /*some computation*/;
    return /*etc*/;
});

[edit May,2021]: la forma teóricamente más breve de definir tal función hoy en día es f=i=>i?[...f(i-1),i]:[]donde reemplazas f con range1 o cualquiera que sea el nombre, pero que sería muy lento (complejidad cuadrática) debido a estructuras intermedias, por lo que nunca debe usarse. f=i=>i?f(i-1)&&x.push(i)&&x:x=[] es una complejidad lineal pero se basa en el abuso de la notación y es ilegible y también contamina las variables globales. Pero, dado que la definición de funciones de flecha (que no se vinculan sino que heredan this) es bastante conciso hoy en día, podría envolver la solución anterior:

const range1 = n=> Array.from(Array(n), (_,i)=> i+i);
// range1(5)==[1, 2, 3, 4, 5]

Circunstancialmente, la manera más breve de hacer una range(N)si ya tiene una lista de exactamente esa longitud N, es solo para map it: por ejemplo, en lugar de hacer Array.from(Array(myArr.length), (_,i)=> i**2)solo harías myArr.map((_,i)=> i**2). (Esto no tiene efectos secundarios a menos que usted lo desee).


todo a continuación es histórico:

Después de pensarlo un poco, esta es la implementación más corta del estándar. range(N) función en JavaScript que podría llegar a:

function range1(i){return i?range1(i-1).concat(i):[]}

Nota: No use esto en producción; es O(N^2)

Contraste con la respuesta actual más votada:

function range1(i){var x=[];var i=1;while(x.push(i++)<i){};return x}

Ejemplo:

> range1(5)
[1, 2, 3, 4, 5]

Esto es como el niño del cartel para la recursividad, aunque esperaba que fuera más largo hasta que pensé en la declaración ternaria si, que lo reduce a 42 caracteres necesarios.

Tenga en cuenta que el “estándar” range función que regresa [start,end) can be written by doing .concat(i-1).


Update: Ooh, I discovered an incredibly short version with ugly imperative syntax by abusing for loops, reverse-ordering, the fact that assignments return a value: for(y=[],i=20;y[--i]=yo;){} que consta de sólo 25 caracteres (aunque querrá var y que puede insertar en un bucle for, y +1 si no desea 0…19). Si bien no es más corto si necesita definir una función, es más corto que i?r(i-1).concat(i):[] si no necesita hacer una función.


Se agregaron algunos casos de prueba de perfiles de rendimiento: parece que todo, además de un bucle for estándar en orden, es 10 veces más lento, al menos en V8. https://jsperf.com/array-range-in-javascript
(Por supuesto, nada de esto importa si está programando en un estilo funcional de todos modos y de todos modos golpearía cada elemento con una llamada de función).

  • ¡Muy agradable! Para hacer un rango 1-20: function range(i) {return i>1 ? range(i-1).concat(i-1) : [];} y use range(21) ;~)

    – KooiInc

    9 de junio de 2011 a las 21:57

  • ¡muy inteligente! Si fuera el OP, elegiría esta respuesta.

    – KooiInc

    10 de junio de 2011 a las 7:49

  • ¡Eso es increíble! Muy buen uso de la recursividad y concat() developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…

    – artlung

    11 de junio de 2011 a las 22:42


  • Sin embargo, debo mencionar que si bien mi respuesta es concisa (como se solicitó), puede que no sea eficiente para rangos grandes, porque .concat de javascript puede no ser una operación O (1) lamentablemente.

    – ninjagecko

    25 de abril de 2012 a las 18:31


  • La primera alternativa de ES6 probablemente arrojará un Supplied parameters do not match any signature of call target. error. Esto se debe a que el fill() El método en el prototipo Array debe recibir el valor de relleno. Mira mi solución para usar el fill()método.

    – Carlos Rosa

    10/09/2016 a las 18:03

Se puede hacer con funciones de ES6, actualmente solo compatible con Firefox. Encontré una tabla de compatibilidad aquí: http://kangax.github.io/compat-table/es6/

Array.from(new Array(20), (x,i) => i+1)

Si quieres tener algún otro rango, entonces supongo que podrías hacerlo

Array.from(new Array(5), (x,i) => i+5)

cual seria entonces [5,6,7,8,9]

  • Esto funciona en Chrome a partir de v45 y se puede usar si está usando Babel para transpilar ES6. también puedes hacer Array.from({ length: 20 }, (v, k) => k + 1);

    – bendman

    9 de septiembre de 2015 a las 2:03

avatar de usuario
En peligroMassa

Puede hacer esto con un bucle while en el que la inserción ocurre dentro de la condición. Array.push devuelve la longitud de la matriz, que resulta ser el mismo que el valor en este caso. Entonces, puedes hacer lo siguiente:

x = []; //normally would use var here
i = 1;  //normally would use var here
while(x.push(i++)<20){}

//at this point, x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

Versión condensada (31 caracteres)

x=[];i=1;while(x.push(i++)<20);

js Ejemplo de violín

  • ¡Vaya! Me gusta eso. Aunque es perverso. Mi entendimiento es que .push() devuelve la longitud de la matriz. En Documentos de Mozilla: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/… “El método push es útil para agregar fácilmente valores a una matriz. El valor de retorno de este método es la nueva propiedad de longitud del objeto sobre el que se llamó al método”. Simplemente sucede que en una matriz que comienza con 1, la última push()ed va a ser la longitud. ¡Decir ah!

    – artlung

    9 de junio de 2011 a las 21:36

  • @EndangeredMassa, x.Push() devuelve la nueva longitud, no el valor.

    – Otro usuario más

    9 de junio de 2011 a las 21:36

  • @EndangeredMassa. ¿Es x.push(i++) igual al número de elementos en x?

    – Hasan Fahim

    9 de junio de 2011 a las 21:38

  • Ah, sí. En este caso específico, son los mismos.

    – Massa en peligro de extinción

    9 de junio de 2011 a las 21:39

  • Está ahorrando espacio al no usar var, pero si implementa esto, use var, o quien mantenga su código lo encontrará …

    – Roberto

    9 de junio de 2011 a las 21:40

avatar de usuario
coco

mientras– es el camino a seguir

var a=[],b=10;while(b--)a[b]=b+1

devoluciones [1,2,3,4,5,6,7,8,9,10]

explicado con inicio y longitud

var array=[],length=20,start=5;while(length--)array[length]=length+start

devoluciones [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]

quieres rango?

explicado con inicio y fin

var array=[],end=30,start=25,a=end-start+1;while(a--)array[a]=end--

devoluciones [25, 26, 27, 28, 29, 30]

por —

for(var a=[],b=20;b>0;b--,a[b]=b+1)

para ++

for(var a=[],b=0;b<20;b++,a[b]=b+1)

¿POR QUÉ es este el camino a seguir?

  1. while — es probablemente el bucle más rápido;

  2. la configuración directa es más rápida que push & concat;

  3. [] también es más rápido que new Array(10);

  4. no es un código mucho más largo que todos los demás

Técnicas de ahorro de bytes:

  1. use los argumentos como marcador de posición para las variables de función
  2. no use new Array(), push(), concat() si no es necesario
  3. coloque “(){};,” solo cuando sea necesario.
  4. use a,b,c,d… en funciones cortas.

así que si quieres una función para esto

con inicio, fin (rango)

function range(a,b,c,d){d=[];c=b-a+1;while(c--)d[c]=b--;return d}

entonces ahora range(3,7) regresa [3,4,5,6,7]

Aquí se guardan bytes de muchas maneras y esta función también es muy rápida, ya que no usa concat, push, new Array y se hace con un tiempo —

avatar de usuario
Killroy

Si está de acuerdo con 0-20, aquí están mis últimos favoritos de golf de código reciente:

[...'0'.repeat(21)].map((_,i)=>i)
Array.from({length:21},(_,i)=>i)
Array(21).fill().map((_,i)=>i)
[...Array(21)].map((_,i)=>i)
Array(21).map((_,i)=>i)
[...Array(21).keys()]

avatar de usuario
carlos rosa

Usando ES6

numArr = Array(5).fill(0).reduce(arr=>{ arr.push(arr.length); return arr },[])

avatar de usuario
Soldeplata Saketos

si acepta tener un contador a partir de 0 en lugar de 1…

const zeroNineteen = [...Array(20).keys()]; 
// outputs [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]

si realmente lo necesita para comenzar con 1:

const terserst = [...Array(21).keys()].slice(1);

tiene 30 caracteres y, sin embargo, es legible, ¿no crees?

  • El mejor tb 🙂

    –Michael Paccione

    16 de abril a las 3:20

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad