array - foreach javascript
¿La forma más eficiente de crear una matriz de JavaScript llena de cero? (30)
¿Cuál es la forma más eficiente de crear una matriz rellena con cero de longitud arbitraria en JavaScript?
Manera elegante de llenar una matriz con valores precomputados.
Aquí hay otra forma de hacerlo usando ES6 que nadie ha mencionado hasta ahora:
> Array.from(Array(3), () => 0)
< [0, 0, 0]
Funciona al pasar una función de mapa como el segundo parámetro de Array.from
.
En el ejemplo anterior, el primer parámetro asigna una matriz de 3 posiciones llenas con el valor undefined
y luego la función lambda asigna cada una de ellas al valor 0
.
Aunque Array(len).fill(0)
es más corto, no funciona si necesita llenar el array haciendo primero un cálculo (Sé que la pregunta no lo hizo, pero muchas personas terminan aquí buscando esto) .
Por ejemplo, si necesita una matriz con 10 números aleatorios:
> Array.from(Array(10), () => Math.floor(10 * Math.random()))
< [3, 6, 8, 1, 9, 3, 0, 6, 7, 1]
Es más conciso (y elegante) que el equivalente:
const numbers = Array(10);
for (let i = 0; i < numbers.length; i++) {
numbers[i] = Math.round(10 * Math.random());
}
Este método también se puede utilizar para generar secuencias de números aprovechando el parámetro de índice proporcionado en la devolución de llamada:
> Array.from(Array(10), (d, i) => i)
< [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Respuesta de bonificación: rellene una matriz utilizando String repeat()
Como esta respuesta está recibiendo mucha atención, también quería mostrar este truco genial. Aunque no es tan útil como mi respuesta principal, presentará el método String repeat()
todavía no muy conocido, pero muy útil. Aquí está el truco:
> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
Genial, ¿eh? repeat()
es un método muy útil para crear una cadena que es la repetición de la cadena original un cierto número de veces. Después de eso, split()
crea una matriz para nosotros, que luego es map()
ped a los valores que queremos. Romperlo en pasos:
> "?".repeat(10)
< "??????????"
> "?".repeat(10).split("")
< ["?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]
> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]
Solución ES6:
[...new Array(5)].map(x => 0); // [0, 0, 0, 0, 0]
¿Qué pasa con la new Array(51).join(''0'').split('''')
?
Aunque este es un hilo viejo, quería agregarle mis 2 centavos. No estoy seguro de qué tan lento / rápido es esto, pero es un forro rápido. Esto es lo que hago:
Si quiero rellenar previamente con un número:
Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
// [0, 0, 0, 0, 0]
Si quiero rellenar previamente con una cadena:
Array.apply(null, Array(3)).map(String.prototype.valueOf,"hi")
// ["hi", "hi", "hi"]
Otras respuestas han sugerido:
new Array(5+1).join(''0'').split('''')
// ["0", "0", "0", "0", "0"]
pero si quieres 0 (el número) y no "0" (cero dentro de una cadena), puedes hacerlo:
new Array(5+1).join(''0'').split('''').map(parseFloat)
// [0, 0, 0, 0, 0]
ES6 introduce Array.prototype.fill
. Se puede usar así:
new Array(len).fill(0);
No estoy seguro de si es rápido, pero me gusta porque es corto y se describe a sí mismo.
Todavía no está en IE ( verifique la compatibilidad ), pero hay un polyfill disponible .
El más corto para el código de bucle
a=i=[];for(;i<100;)a[i++]=0;
edit:
for(a=i=[];i<100;)a[i++]=0;
or
for(a=[],i=100;i--;)a[i]=0;
Versión var segura
var a=[],i=0;for(;i<100;)a[i++]=0;
edit:
for(var i=100,a=[];i--;)a[i]=0;
El ya mencionado método de llenado ES 6 se encarga de esto muy bien. La mayoría de los navegadores de escritorio modernos ya admiten los métodos de prototipos de Array requeridos a partir de hoy (Chromium, FF, Edge y Safari) [ 1 ]. Puedes buscar detalles en Array.prototype.fill . Un ejemplo de uso simple es
a = new Array(10).fill(0);
Teniendo en cuenta la compatibilidad actual con el navegador, debe tener cuidado de usar esto a menos que esté seguro de que su audiencia utiliza navegadores de escritorio modernos.
Esta versión concat
es mucho más rápida en mis pruebas en Chrome (2013-03-21). Alrededor de 200ms para 10,000,000 elementos vs 675 para init directo.
function filledArray(len, value) {
if (len <= 0) return [];
var result = [value];
while (result.length < len/2) {
result = result.concat(result);
}
return result.concat(result.slice(0, len-result.length));
}
Bonificación: si desea llenar su matriz con cadenas, esta es una forma concisa de hacerlo (aunque no tan rápido como concat
):
function filledArrayString(len, value) {
return new Array(len+1).join(value).split('''');
}
Estaba probando la gran respuesta de TJ Crowder y se me ocurrió una combinación recursiva basada en la solución concat que supera a cualquiera de sus pruebas en Chrome (no probé otros navegadores).
function makeRec(len, acc) {
if (acc == null) acc = [];
if (len <= 1) return acc;
var b = makeRec(len >> 1, [0]);
b = b.concat(b);
if (len & 1) b = b.concat([0]);
return b;
},
Llame al método con makeRec(29)
.
He probado todas las combinaciones de pre-asignación / no pre-asignación, contando arriba / abajo y para / while bucles en IE 6/7/8, Firefox 3.5, Chrome y Opera.
Las funciones a continuación fueron consistentemente las más rápidas o extremadamente cercanas en Firefox, Chrome e IE8, y no mucho más lentas que las más rápidas en Opera e IE 6. También es la más simple y clara en mi opinión. He encontrado varios navegadores en los que la versión while loop es un poco más rápida, por lo que también la incluyo como referencia.
function newFilledArray(length, val) {
var array = [];
for (var i = 0; i < length; i++) {
array[i] = val;
}
return array;
}
o
function newFilledArray(length, val) {
var array = [];
var i = 0;
while (i < length) {
array[i++] = val;
}
return array;
}
La forma en que normalmente lo hago (y es increíblemente rápido) es usar Uint8Array
. Por ejemplo, creando un vector lleno de cero de elementos 1M:
var zeroFilled = [].slice.apply(new Uint8Array(1000000))
Soy un usuario de Linux y siempre he trabajado para mí, pero una vez que un amigo que usaba una Mac tenía algunos elementos que no eran cero. Pensé que su máquina estaba funcionando mal, pero aún así, aquí está la forma más segura que encontramos para solucionarlo:
var zeroFilled = [].slice.apply(new Uint8Array(new Array(1000000))
Editado
Chrome 25.0.1364.160
- Frederik Gottlieb - 6.43
- Sam Barnum - 4.83
- Eli - 3.68
- Joshua 2,91
- Mathew Crumley - 2,67
- bduran - 2.55
- Allen Rice - 2.11
- Kangax - 0.68
- Tj. Crowder - 0.67
- zertosh - ERROR
Firefox 20.0
- Allen Rice - 1.85
- Joshua - 1.82
- Mathew Crumley - 1.79
- bduran - 1.37
- Frederik Gottlieb - 0.67
- Sam Barnum - 0.63
- Eli - 0.59
- kagax - 0.13
- Tj. Crowder - 0.13
- zertosh - ERROR
Falta la prueba más importante (al menos para mí): la de Node.js. Sospecho que se acerca al punto de referencia de Chrome.
Mi función más rápida sería:
function newFilledArray(len, val) {
var a = [];
while(len--){
a.push(val);
}
return a;
}
var st = (new Date()).getTime();
newFilledArray(1000000, 0)
console.log((new Date()).getTime() - st); // returned 63, 65, 62 milliseconds
Usar el push y shift nativo para agregar elementos a la matriz es mucho más rápido (aproximadamente 10 veces) que declarar el alcance de la matriz y hacer referencia a cada elemento para establecer su valor.
fyi: Siempre obtengo tiempos más rápidos con el primer bucle, que es la cuenta regresiva, cuando se ejecuta esto en firebug (extensión de Firefox).
var a = [];
var len = 1000000;
var st = (new Date()).getTime();
while(len){
a.push(0);
len -= 1;
}
console.log((new Date()).getTime() - st); // returned 863, 894, 875 milliseconds
st = (new Date()).getTime();
len = 1000000;
a = [];
for(var i = 0; i < len; i++){
a.push(0);
}
console.log((new Date()).getTime() - st); // returned 1155, 1179, 1163 milliseconds
¿Me interesa saber qué hace TJ Crowder de eso? :-)
No tengo nada en contra:
Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
new Array(5+1).join(''0'').split('''').map(parseFloat);
Sugerido por Zertosh, pero en una nueva matriz ES6, las extensiones le permiten hacer esto de forma nativa con el método de fill
. Ahora IE edge, Chrome y FF lo admiten, pero compruebe la tabla de compatibilidad
new Array(3).fill(0)
le dará [0, 0, 0]
. Puede rellenar la matriz con cualquier valor como la new Array(5).fill(''abc'')
(incluso los objetos y otras matrices).
Además, puedes modificar matrices anteriores con relleno:
arr = [1, 2, 3, 4, 5, 6]
arr.fill(9, 3, 5) # what to fill, start, end
que te da: [1, 2, 3, 9, 9, 6]
No vi este método en las respuestas, así que aquí está:
"0".repeat( 200 ).split("").map( parseFloat )
En el resultado obtendrá una matriz de longitud 200 de valor cero:
[ 0, 0, 0, 0, ... 0 ]
No estoy seguro del rendimiento de este código, pero no debería ser un problema si lo usa para arreglos relativamente pequeños.
Por defecto, las clases Uint8Array
, Uint16Array
y Uint32Array
mantienen los ceros como sus valores, por lo que no necesita ninguna técnica de relleno compleja, simplemente haga lo siguiente:
var ary = new Uint8Array(10);
Todos los elementos de array ary
serán ceros por defecto.
Sabía que tenía este proto''d en algún lugar :)
Array.prototype.init = function(x,n)
{
if(typeof(n)==''undefined'') { n = this.length; }
while (n--) { this[n] = x; }
return this;
}
var a = (new Array(5)).init(0);
var b = [].init(0,4);
Editar: pruebas
En respuesta a los métodos de Joshua y otros, realicé mi propia evaluación comparativa y veo resultados completamente diferentes a los reportados.
Esto es lo que he probado:
//my original method
Array.prototype.init = function(x,n)
{
if(typeof(n)==''undefined'') { n = this.length; }
while (n--) { this[n] = x; }
return this;
}
//now using push which I had previously thought to be slower than direct assignment
Array.prototype.init2 = function(x,n)
{
if(typeof(n)==''undefined'') { n = this.length; }
while (n--) { this.push(x); }
return this;
}
//joshua''s method
function newFilledArray(len, val) {
var a = [];
while(len--){
a.push(val);
}
return a;
}
//test m1 and m2 with short arrays many times 10K * 10
var a = new Date();
for(var i=0; i<10000; i++)
{
var t1 = [].init(0,10);
}
var A = new Date();
var b = new Date();
for(var i=0; i<10000; i++)
{
var t2 = [].init2(0,10);
}
var B = new Date();
//test m1 and m2 with long array created once 100K
var c = new Date();
var t3 = [].init(0,100000);
var C = new Date();
var d = new Date();
var t4 = [].init2(0,100000);
var D = new Date();
//test m3 with short array many times 10K * 10
var e = new Date();
for(var i=0; i<10000; i++)
{
var t5 = newFilledArray(10,0);
}
var E = new Date();
//test m3 with long array created once 100K
var f = new Date();
var t6 = newFilledArray(100000, 0)
var F = new Date();
Resultados:
IE7 deltas:
dA=156
dB=359
dC=125
dD=375
dE=468
dF=412
FF3.5 deltas:
dA=6
dB=13
dC=63
dD=8
dE=12
dF=8
Por lo tanto, según mi opinión, el impulso en general es más lento, pero funciona mejor con arreglos más largos en FF pero peor en IE, que simplemente apesta en general (sorpresa de quel)
Si necesita crear muchos arreglos llenos de cero de diferentes longitudes durante la ejecución de su código, la forma más rápida que he encontrado para lograrlo es crear un arreglo de cero una vez , utilizando uno de los métodos mencionados en este tema, de una longitud que usted sabe que nunca se superará, y luego cortar esa matriz según sea necesario.
Por ejemplo (utilizando la función de la respuesta elegida anteriormente para inicializar la matriz), cree una matriz rellena con cero de longitud maxLength , como una variable visible para el código que necesita matrices cero:
var zero = newFilledArray(maxLength, 0);
Ahora rebana esta matriz cada vez que necesites una matriz llena de cero de longitud requiredLength < maxLength :
zero.slice(0, requiredLength);
Estaba creando arreglos con cero miles de veces durante la ejecución de mi código, lo que aceleró enormemente el proceso.
Si usa ES6, puede usar Array.from siguiente manera:
Array.from({ length: 3 }, () => 0);
//[0, 0, 0]
Tiene el mismo resultado que
Array.from({ length: 3 }).map(() => 0)
//[0, 0, 0]
Porque
Array.from({ length: 3 })
//[undefined, undefined, undefined]
Usando lodash o underscore
_.range(0, length - 1, 0);
O si tiene una matriz existente y desea una matriz de la misma longitud
array.map(_.constant(0));
usando notación de objetos
var x = [];
lleno de cero? me gusta...
var x = [0,0,0,0,0,0];
Lleno de ''indefinido'' ...
var x = new Array(7);
notación obj con ceros
var x = [];
for (var i = 0; i < 10; i++) x[i] = 0;
Como nota al margen, si modifica el prototipo de Array, ambos
var x = new Array();
y
var y = [];
Tendrá esas modificaciones prototipo
En cualquier caso, no me preocuparía demasiado la eficiencia o la velocidad de esta operación, hay muchas otras cosas que probablemente esté haciendo que son mucho más innecesarias y costosas que la creación de una serie de longitudes arbitrarias que contienen ceros.
Nota agregada en agosto de 2013, actualizada en febrero de 2015: la respuesta a continuación de 2009 se relaciona con el tipo genérico de Array
JavaScript. No se relaciona con los arreglos escritos más nuevos definidos en ES2015 [y disponibles ahora en muchos navegadores], como Int32Array
y similares. También tenga en cuenta que ES2015 agrega un método de fill
tanto a las Arrays como a las Arrays mecanografiadas , que probablemente sea la forma más eficiente de llenarlas ...
Además, puede hacer una gran diferencia en algunas implementaciones de cómo crear la matriz. El motor V8 de Chrome, en particular, intenta utilizar una matriz de memoria contigua altamente eficiente si cree que puede, cambiando a la matriz basada en objetos solo cuando sea necesario.
Con la mayoría de los idiomas, se asignaría previamente, luego se rellenaría con cero, de esta manera:
function newFilledArray(len, val) {
var rv = new Array(len);
while (--len >= 0) {
rv[len] = val;
}
return rv;
}
Pero , las matrices de JavaScript no son realmente matrices , son mapas de clave / valor al igual que todos los demás objetos de JavaScript, por lo que no hay que hacer una "asignación previa" (establecer la longitud no asigna tantas ranuras para rellenar), ni ¿Hay alguna razón para creer que el beneficio de contar en cero (que es solo para hacer la comparación en el bucle rápido) no se ve compensado por agregar las claves en orden inverso cuando la implementación bien puede haber optimizado su manejo de las claves? En relación con las matrices de la teoría, generalmente las hará en orden.
De hecho, Matthew Crumley señaló que la cuenta regresiva es notablemente más lenta en Firefox que la cuenta regresiva, un resultado que puedo confirmar: es la parte de la matriz (el bucle a cero es aún más rápido que el bucle hasta un límite en una var). Aparentemente, agregar los elementos a la matriz en orden inverso es una operación lenta en Firefox. De hecho, los resultados varían bastante según la implementación de JavaScript (que no es tan sorprendente). Aquí hay una página de prueba rápida y sucia (a continuación) para las implementaciones del navegador (muy sucia, no cede durante las pruebas, por lo que proporciona una retroalimentación mínima y se opondrá a los límites de tiempo del script) Recomiendo refrescar entre pruebas; FF (al menos) disminuye la velocidad en pruebas repetidas si no lo hace.
La versión bastante complicada que usa Array # concat es más rápida que un inicio directo en FF a partir de entre 1.000 y 2.000 arreglos de elementos. Sin embargo, en el motor V8 de Chrome, el init directo gana cada vez ...
Aquí está la página de prueba ( copia en vivo ):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Zero Init Test Page</title>
<style type=''text/css''>
body {
font-family: sans-serif;
}
#log p {
margin: 0;
padding: 0;
}
.error {
color: red;
}
.winner {
color: green;
font-weight: bold;
}
</style>
<script type=''text/javascript'' src=''prototype-1.6.0.3.js''></script>
<script type=''text/javascript''>
var testdefs = {
''downpre'': {
total: 0,
desc: "Count down, pre-decrement",
func: makeWithCountDownPre
},
''downpost'': {
total: 0,
desc: "Count down, post-decrement",
func: makeWithCountDownPost
},
''up'': {
total: 0,
desc: "Count up (normal)",
func: makeWithCountUp
},
''downandup'': {
total: 0,
desc: "Count down (for loop) and up (for filling)",
func: makeWithCountDownArrayUp
},
''concat'': {
total: 0,
desc: "Concat",
func: makeWithConcat
}
};
document.observe(''dom:loaded'', function() {
var markup, defname;
markup = "";
for (defname in testdefs) {
markup +=
"<div><input type=''checkbox'' id=''chk_" + defname + "'' checked>" +
"<label for=''chk_" + defname + "''>" + testdefs[defname].desc + "</label></div>";
}
$(''checkboxes'').update(markup);
$(''btnTest'').observe(''click'', btnTestClick);
});
function epoch() {
return (new Date()).getTime();
}
function btnTestClick() {
// Clear log
$(''log'').update(''Testing...'');
// Show running
$(''btnTest'').disabled = true;
// Run after a pause while the browser updates display
btnTestClickPart2.defer();
}
function btnTestClickPart2() {
try {
runTests();
}
catch (e) {
log("Exception: " + e);
}
// Re-enable the button; we don''t yheidl
$(''btnTest'').disabled = false;
}
function runTests() {
var start, time, counter, length, defname, def, results, a, invalid, lowest, s;
// Get loops and length
s = $F(''txtLoops'');
runcount = parseInt(s);
if (isNaN(runcount) || runcount <= 0) {
log("Invalid loops value ''" + s + "''");
return;
}
s = $F(''txtLength'');
length = parseInt(s);
if (isNaN(length) || length <= 0) {
log("Invalid length value ''" + s + "''");
return;
}
// Clear log
$(''log'').update('''');
// Do it
for (counter = 0; counter <= runcount; ++counter) {
for (defname in testdefs) {
def = testdefs[defname];
if ($(''chk_'' + defname).checked) {
start = epoch();
a = def.func(length);
time = epoch() - start;
if (counter == 0) {
// Don''t count (warm up), but do check the algorithm works
invalid = validateResult(a, length);
if (invalid) {
log("<span class=''error''>FAILURE</span> with def " + defname + ": " + invalid);
return;
}
}
else {
// Count this one
log("#" + counter + ": " + def.desc + ": " + time + "ms");
def.total += time;
}
}
}
}
for (defname in testdefs) {
def = testdefs[defname];
if ($(''chk_'' + defname).checked) {
def.avg = def.total / runcount;
if (typeof lowest != ''number'' || lowest > def.avg) {
lowest = def.avg;
}
}
}
results =
"<p>Results:" +
"<br>Length: " + length +
"<br>Loops: " + runcount +
"</p>";
for (defname in testdefs) {
def = testdefs[defname];
if ($(''chk_'' + defname).checked) {
results += "<p" + (lowest == def.avg ? " class=''winner''" : "") + ">" + def.desc + ", average time: " + def.avg + "ms</p>";
}
}
results += "<hr>";
$(''log'').insert({top: results});
}
function validateResult(a, length) {
var n;
if (a.length != length) {
return "Length is wrong";
}
for (n = length - 1; n >= 0; --n) {
if (a[n] != 0) {
return "Index " + n + " is not zero";
}
}
return undefined;
}
function makeWithCountDownPre(len) {
var a;
a = new Array(len);
while (--len >= 0) {
a[len] = 0;
}
return a;
}
function makeWithCountDownPost(len) {
var a;
a = new Array(len);
while (len-- > 0) {
a[len] = 0;
}
return a;
}
function makeWithCountUp(len) {
var a, i;
a = new Array(len);
for (i = 0; i < len; ++i) {
a[i] = 0;
}
return a;
}
function makeWithCountDownArrayUp(len) {
var a, i;
a = new Array(len);
i = 0;
while (--len >= 0) {
a[i++] = 0;
}
return a;
}
function makeWithConcat(len) {
var a, rem, currlen;
if (len == 0) {
return [];
}
a = [0];
currlen = 1;
while (currlen < len) {
rem = len - currlen;
if (rem < currlen) {
a = a.concat(a.slice(0, rem));
}
else {
a = a.concat(a);
}
currlen = a.length;
}
return a;
}
function log(msg) {
$(''log'').appendChild(new Element(''p'').update(msg));
}
</script>
</head>
<body><div>
<label for=''txtLength''>Length:</label><input type=''text'' id=''txtLength'' value=''10000''>
<br><label for=''txtLoops''>Loops:</label><input type=''text'' id=''txtLoops'' value=''10''>
<div id=''checkboxes''></div>
<br><input type=''button'' id=''btnTest'' value=''Test''>
<hr>
<div id=''log''></div>
</div></body>
</html>
A partir de ECMAScript2016 , hay una opción clara para los arreglos grandes.
Dado que esta respuesta aún aparece en la parte superior de las búsquedas de Google, aquí hay una respuesta para 2017.
Aquí hay un jsbench actual con algunas docenas de métodos populares, incluyendo muchos propuestos hasta ahora en esta pregunta. Si encuentra un método mejor, por favor agregue, bifurque y comparta.
Quiero tener en cuenta que no existe una manera verdadera y eficiente de crear una matriz rellena con cero de longitud arbitraria. Puede optimizar la velocidad o la claridad y la capacidad de mantenimiento; cualquiera de los dos puede considerarse la opción más eficiente según las necesidades del proyecto.
Al optimizar la velocidad, usted desea: crear la matriz usando una sintaxis literal; establecer la longitud, inicializar la variable de iteración e iterar a través de la matriz utilizando un bucle while. Aquí hay un ejemplo.
const arr = [];
arr.length = 120000;
let i = 0;
while (i < 120000) {
arr[i] = 0;
i++;
}
Otra posible implementación sería:
(arr = []).length = n;
let i = 0;
while (i < n) {
arr[i] = 0;
i++;
}
Pero desaconsejo el uso de este segundo implante en la práctica, ya que es menos claro y no le permite mantener el alcance del bloque en su variable de matriz.
Estos son significativamente más rápidos que el llenado con un bucle for, y aproximadamente un 90% más rápido que el método estándar de
const arr = Array(n).fill(0);
Pero este método de relleno sigue siendo la opción más eficiente para arreglos más pequeños debido a su claridad, concisión y capacidad de mantenimiento. La diferencia de rendimiento probablemente no lo matará a menos que esté haciendo muchos arreglos con longitudes del orden de miles o más.
Algunas otras notas importantes. La mayoría de las guías de estilo recomiendan que ya no uses var
sin un motivo muy especial al usar ES6 o posterior. Use const
para las variables que no se redefinirán y let
variables que lo harán. La Guía de estilo de MDN y Airbnb son excelentes lugares para obtener más información sobre las mejores prácticas. Las preguntas no se referían a la sintaxis, pero es importante que las personas nuevas en JS conozcan estos nuevos estándares al buscar en estas resmas de respuestas antiguas y nuevas.
Función anónima:
(function(n) { while(n-- && this.push(0)); return this; }).call([], 5);
// => [0, 0, 0, 0, 0]
Un poco más corto con for-loop:
(function(n) { for(;n--;this.push(0)); return this; }).call([], 5);
// => [0, 0, 0, 0, 0]
Funciona con cualquiera Object
, solo cambia lo que hay dentro this.push()
.
Incluso puedes guardar la función:
function fill(size, content) {
for(;size--;this.push(content));
return this;
}
Llámalo usando:
var helloArray = fill.call([], 5, ''hello'');
// => [''hello'', ''hello'', ''hello'', ''hello'', ''hello'']
Añadiendo elementos a una matriz ya existente:
var helloWorldArray = fill.call(helloArray, 5, ''world'');
// => [''hello'', ''hello'', ''hello'', ''hello'', ''hello'', ''world'', ''world'', ''world'', ''world'', ''world'']
Rendimiento: http://jsperf.com/zero-filled-array-creation/25
La forma más rápida de hacerlo es con forEach =)
(Mantenemos la compatibilidad con versiones anteriores para IE <9)
var fillArray = Array.prototype.forEach
? function(arr, n) {
arr.forEach(function(_, index) { arr[index] = n; });
return arr;
}
: function(arr, n) {
var len = arr.length;
arr.length = 0;
while(len--) arr.push(n);
return arr;
};
// test
fillArray([1,2,3], ''X''); // => [''X'', ''X'', ''X'']
Siempre existe la solución phpjs, que puedes encontrar aquí:
http://phpjs.org/functions/array_fill/
No puedo hablar sobre el proyecto (crear una biblioteca de funciones javascript que refleje la mayor funcionalidad de php) en su conjunto, pero las pocas funciones que personalmente he extraído de allí han funcionado como un campeón.
Yo solo uso
var arr = [10];
for (var i=0; i<=arr.length;arr[i] = i, i++);
Podría valer la pena señalar, que se Array.prototype.fill
había agregado como parte de la propuesta ECMAScript 6 (Harmony) . Preferiría ir con el polyfill escrito a continuación, antes de considerar otras opciones mencionadas en el hilo.
if (!Array.prototype.fill) {
Array.prototype.fill = function(value) {
// Steps 1-2.
if (this == null) {
throw new TypeError(''this is null or not defined'');
}
var O = Object(this);
// Steps 3-5.
var len = O.length >>> 0;
// Steps 6-7.
var start = arguments[1];
var relativeStart = start >> 0;
// Step 8.
var k = relativeStart < 0 ?
Math.max(len + relativeStart, 0) :
Math.min(relativeStart, len);
// Steps 9-10.
var end = arguments[2];
var relativeEnd = end === undefined ?
len : end >> 0;
// Step 11.
var final = relativeEnd < 0 ?
Math.max(len + relativeEnd, 0) :
Math.min(relativeEnd, len);
// Step 12.
while (k < final) {
O[k] = value;
k++;
}
// Step 13.
return O;
};
}
function makeArrayOf(value, length) {
var arr = [], i = length;
while (i--) {
arr[i] = value;
}
return arr;
}
makeArrayOf(0, 5); // [0, 0, 0, 0, 0]
makeArrayOf(''x'', 3); // [''x'', ''x'', ''x'']
Tenga en cuenta que while
que generalmente es más eficiente que for-in
, forEach
, etc.
function zeroFilledArray(size) {
return new Array(size + 1).join(''0'').split('''');
}
var str = "0000000...0000";
var arr = str.split("");
uso en expresiones: arr[i]*1;
EDITAR: si se arr
supone que debe usarse en expresiones enteras, entonces no le importa el valor char de ''0''. Solo lo usa de la siguiente manera: a = a * arr[i]
(asumiendo que a
tiene un valor entero).