sort - w3schools javascript array methods




Maneira mais eficiente de criar um array JavaScript preenchido com zero? (20)

Qual é a maneira mais eficiente de criar um array com comprimento zero arbitrário em JavaScript?


MAIS BREVE

Array(n).fill(0)

(16 char), onde n é o tamanho da matriz

2018.10.28 fiz comparação de desempenho de 15 proposições de outras respostas. Os testes foram feitos no Mac OS X 10.13.6 High Sierra, em três navegadores: Chrome 69.0.3497, Safari 12.0 (13606.2.11) e Firefox 63.0 (64 bit).

Resultado para n = 100000

Abaixo eu mostro resultados para o navegador mais rápido (safari):

Para todos os navegadores, a solução mais rápida era M - no entanto, não é "array típico" (mas muito rápido) - operações do Safari 33.8k / segundo, Chrome 5.2k, FF 3.5k,

Soluções mais rápidas para matrizes típicas:

  • A e B (era semelhante) para o Safari 5.5k e o Chrome 1.1k (no Firefox A 0.1k, B 0.06k)
  • F para o Firefox 0.6k (no Safari 3.1k, Chrome 1.1k)
  • para os resultados do Chrome e Safari A, B, F estava próximo

A solução mais lenta:

  • G para Safari 0.02k e Firefox 0.04k (no Chrome 0.1k)
  • D para o Chrome 0.04k (no Safari 0.33k, no Firefox 0.15k)

A solução N funciona apenas no Firefox e no Chrome.

Resultado para n = 10

O mais rápido:

  • M foi mais rápido no Chrome 17.3M e no Safari 13.3M (Firefox 4.7M)
  • A, B foi semelhante e mais rápido no Firefox 16.9M (Chrome 15.6M, Safari 3.5M)

Mais devagar:

  • O para o Safari 0.35M
  • K para o Chrome 0.35M
  • N para o Firefox 0.31M

CONCLUSÃO

  • a solução mais rápida em todos os navegadores (exceto small n no Firefox) foi M let a = new Float32Array(n) (no entanto não é típico array) - para ele o navegador mais rápido foi o Safari (para grandes n > 6x mais rápido que o Chrome,> 9x mais rápido que o firefox)
  • para matrizes típicas, a solução preferida é A let a = Array(n).fill(0) (código rápido e curto)

Você pode realizar testes em sua máquina here .


Maneira elegante de preencher uma matriz com valores pré-computados

Aqui está outra maneira de fazer isso usando o ES6 que ninguém mencionou até agora:

> Array.from(Array(3), () => 0)
< [0, 0, 0]

Ele funciona passando uma função de mapa como o segundo parâmetro de Array.from .

No exemplo acima, o primeiro parâmetro aloca uma matriz de 3 posições preenchidas com o valor undefined e, em seguida, a função lambda mapeia cada uma delas para o valor 0 .

Embora Array(len).fill(0) seja mais curto, ele não funciona se você precisar preencher o array fazendo algum cálculo primeiro (eu sei que a pergunta não foi solicitada, mas muitas pessoas acabam aqui procurando por isso) .

Por exemplo, se você precisar de um array com 10 números aleatórios:

> Array.from(Array(10), () => Math.floor(10 * Math.random()))
< [3, 6, 8, 1, 9, 3, 0, 6, 7, 1]

É mais conciso (e elegante) que o equivalente:

const numbers = Array(10);
for (let i = 0; i < numbers.length; i++) {
    numbers[i] = Math.round(10 * Math.random());
}

Esse método também pode ser usado para gerar seqüências de números, aproveitando o parâmetro de índice fornecido no retorno de chamada:

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

Resposta de bônus: preencha uma matriz usando String repeat()

Como essa resposta está chamando muita atenção, também queria mostrar esse truque legal. Embora não seja tão útil quanto a minha resposta principal, irá introduzir o método repeat() String ainda não muito conhecido, mas muito útil. Aqui está o truque:

> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]

Legal né? repeat() é um método muito útil para criar uma string que é a repetição da string original um certo número de vezes. Depois disso, split() cria uma matriz para nós, que é então map() ped para os valores que queremos. Quebrando em etapas:

> "?".repeat(10)
< "??????????"

> "?".repeat(10).split("")
< ["?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]

> "?".repeat(10).split("").map(() => Math.floor(10 * Math.random()))
< [5, 6, 3, 5, 0, 8, 2, 7, 4, 1]

A maneira que eu costumo fazer isso (e é incrível rápido) está usando o Uint8Array . Por exemplo, criando um vetor preenchido com zero de elementos 1M:

  var zeroFilled = [].slice.apply(new Uint8Array(1000000))

Sou usuário de Linux e sempre trabalhei para mim, mas uma vez que um amigo usando um Mac tinha alguns elementos diferentes de zero. Eu achei que a máquina dele estava com defeito, mas ainda assim é a maneira mais segura que encontramos para consertar:

  var zeroFilled = [].slice.apply(new Uint8Array(new Array(1000000)) 

Editado

Chrome 25.0.1364.160

  1. Frederik Gottlieb - 6,43
  2. Sam Barnum - 4,83
  3. Eli - 3,68
  4. Josué 2,91
  5. Mathew Crumley - 2,67
  6. bduran - 2,55
  7. Arroz Allen - 2,11
  8. kangax - 0,68
  9. Tj. Crowder - 0,67
  10. zertosh - ERRO

Firefox 20.0

  1. Arroz Allen - 1,85
  2. Josué - 1,82
  3. Mathew Crumley - 1,79
  4. bduran - 1,37
  5. Frederik Gottlieb - 0,67
  6. Sam Barnum - 0,63
  7. Eli - 0,59
  8. kagax - 0.13
  9. Tj. Crowder - 0,13
  10. zertosh - ERRO

Faltando o teste mais importante (pelo menos para mim): o do Node.js. Eu suspeito que perto do benchmark do Chrome.


Embora este seja um segmento antigo, eu queria adicionar meus 2 centavos para ele. Não sei o quão lento / rápido isso é, mas é um rápido um forro. Aqui está o que eu faço:

Se eu quiser preencher previamente com um número:

Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
// [0, 0, 0, 0, 0]

Se eu quiser preencher previamente com uma string:

Array.apply(null, Array(3)).map(String.prototype.valueOf,"hi")
// ["hi", "hi", "hi"]

Outras respostas sugeriram:

new Array(5+1).join('0').split('')
// ["0", "0", "0", "0", "0"]

mas se você quiser 0 (o número) e não "0" (zero dentro de uma string), você pode fazer:

new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]

Eu não tenho nada contra:

Array.apply(null, Array(5)).map(Number.prototype.valueOf,0);
new Array(5+1).join('0').split('').map(parseFloat);

sugerido por Zertosh, mas em um novo ES6 array extensões permitem que você faça isso nativamente com o método de fill . Agora borda IE, Chrome e FF suporta, mas verifique a tabela de compatibilidade

new Array(3).fill(0) lhe dará [0, 0, 0] . Você pode preencher o array com qualquer valor como new Array(5).fill('abc') (até mesmo objetos e outros arrays).

Além disso, você pode modificar os arrays anteriores com preenchimento:

arr = [1, 2, 3, 4, 5, 6]
arr.fill(9, 3, 5)  # what to fill, start, end

que te dá: [1, 2, 3, 9, 9, 6]


Eu testei todas as combinações de pré-alocação / não pré-alocação, contando para cima / para baixo e para / enquanto loops no IE 6/7/8, Firefox 3.5, Chrome e Opera.

As funções abaixo eram consistentemente as mais rápidas ou extremamente próximas no Firefox, Chrome e IE8, e não muito mais lentas que as mais rápidas no Opera e no IE 6. Também é a mais simples e clara na minha opinião. Eu encontrei vários navegadores onde a versão do loop while é um pouco mais rápida, então estou incluindo também para referência.

function newFilledArray(length, val) {
    var array = [];
    for (var i = 0; i < length; i++) {
        array[i] = val;
    }
    return array;
}

ou

function newFilledArray(length, val) {
    var array = [];
    var i = 0;
    while (i < length) {
        array[i++] = val;
    }
    return array;
}


O método de preenchimento ES 6 já mencionado cuida disso bem. A maioria dos navegadores de desktop modernos já suporta os métodos de protótipo Array necessários a partir de hoje (Chromium, FF, Edge e Safari) [ 1 ]. Você pode procurar detalhes sobre o Array.prototype.fill . Um exemplo de uso simples é

a = new Array(10).fill(0);

Dado o suporte atual do navegador, você deve ser cauteloso para usar isso, a menos que tenha certeza de que seu público-alvo usa navegadores modernos do Google Desktop.


Que tal o new Array(51).join('0').split('') ?


Se você precisar criar muitos arrays preenchidos com zero de comprimentos diferentes durante a execução do seu código, a maneira mais rápida que encontrei para conseguir isso é criar um array zero uma vez , usando um dos métodos mencionados neste tópico, de uma extensão que você sabe que nunca será excedido e, em seguida, divida essa matriz conforme necessário.

Por exemplo (usando a função da resposta escolhida acima para inicializar a matriz), crie uma matriz preenchida com zero de comprimento maxLength , como uma variável visível para o código que precisa de matrizes iguais a zero:

var zero = newFilledArray(maxLength, 0);

Agora, corte essa matriz toda vez que precisar de uma matriz preenchida com zero de comprimento requiredLength < maxLength :

zero.slice(0, requiredLength);

Eu estava criando matrizes preenchidas zero milhares de vezes durante a execução do meu código, isso acelerou o processo tremendamente.


Usando lodash ou underscore

_.range(0, length - 1, 0);

Ou se você tem um array existente e você quer um array do mesmo tamanho

array.map(_.constant(0));

usando notação de objeto

var x = [];

preenchido com zero? gostar...

var x = [0,0,0,0,0,0];

preenchido com 'indefinido' ...

var x = new Array(7);

notação obj com zeros

var x = [];
for (var i = 0; i < 10; i++) x[i] = 0;

Como uma nota lateral, se você modificar o protótipo do Array, ambos

var x = new Array();

e

var y = [];

terá essas modificações de protótipo

De qualquer forma, eu não ficaria excessivamente preocupado com a eficiência ou a velocidade dessa operação, há muitas outras coisas que você provavelmente fará que são muito mais dispendiosas e dispendiosas do que instanciar uma série de comprimentos arbitrários contendo zeros.


A partir do ECMAScript2016 , há uma opção clara para grandes matrizes.

Como esta resposta ainda aparece perto do topo das pesquisas do google, aqui está uma resposta para 2017.

Aqui está um jsbench atual com algumas dezenas de métodos populares, incluindo muitos propostos até agora sobre esta questão. Se você encontrar um método melhor, por favor adicione, garfo e compartilhar.

Quero observar que não existe uma maneira realmente eficiente de criar um array com comprimento zero arbitrário. Você pode otimizar a velocidade, ou para clareza e facilidade de manutenção - pode ser considerada a escolha mais eficiente, dependendo das necessidades do projeto.

Ao otimizar a velocidade, você deseja: criar a matriz usando a sintaxe literal; defina o comprimento, inicialize a variável de iteração e itere o array usando um loop while. Aqui está um exemplo.

const arr = [];
arr.length = 120000;
let i = 0;
while (i < 120000) {
  arr[i] = 0;
  i++;
}

Outra implementação possível seria:

(arr = []).length = n;
let i = 0;
while (i < n) {
    arr[i] = 0;
    i++;
}

Mas eu desestimulo fortemente o uso dessa segunda implantação na prática, pois ela é menos clara e não permite que você mantenha o escopo do bloco em sua variável array.

Estes são significativamente mais rápidos do que preencher com um loop for, e cerca de 90% mais rápido do que o método padrão de

const arr = Array(n).fill(0);

Mas esse método de preenchimento ainda é a opção mais eficiente para matrizes menores devido à sua clareza, concisão e facilidade de manutenção. A diferença de desempenho provavelmente não o matará, a menos que você esteja fazendo muitos arrays com comprimentos da ordem de milhares ou mais.

Algumas outras notas importantes. A maioria dos guias de estilo recomendam que você não use mais var sem um motivo muito especial ao usar o ES6 ou posterior. Use const para variáveis ​​que não serão redefinidas e let para variáveis ​​que serão. O Guia de Estilo do MDN e do Airbnb são ótimos lugares para obter mais informações sobre as práticas recomendadas. As perguntas não eram sobre sintaxe, mas é importante que as pessoas que são novas no JS conheçam esses novos padrões ao pesquisar essas resmas de respostas antigas e novas.


A maneira mais rápida de fazer isso é com forEach =)

(mantemos a compatibilidade com versões anteriores do 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']

Há sempre a solução phpjs, que você pode encontrar aqui:

http://phpjs.org/functions/array_fill/

Eu não posso falar pelo projeto (criando uma biblioteca de funções javascript que espelha a maior funcionalidade do php) como um todo, mas as poucas funções que eu pessoalmente tirei de lá funcionaram como um campeão.


Menor para o código de loop

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;

Versão var segura

var a=[],i=0;for(;i<100;)a[i++]=0;

edit:
for(var i=100,a=[];i--;)a[i]=0;

Esta concatversão é muito mais rápida nos meus testes no Chrome (2013-03-21). Cerca de 200ms para 10.000.000 elementos vs 675 para init direto.

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

Bônus: se você quiser preencher sua matriz com Strings, esta é uma maneira concisa de fazê-lo (não tão rápido quanto concat):

function filledArrayString(len, value) {
    return new Array(len+1).join(value).split('');
}

Pode valer a pena ressaltar que isso Array.prototype.fillfoi adicionado como parte da proposta ECMAScript 6 (Harmony) . Eu preferiria ir com o polyfill escrito abaixo, antes de considerar outras opções mencionadas no encadeamento.

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 zeroFilledArray(size) {
    return new Array(size + 1).join('0').split('');
}

new Array(7).fill(0) //Array with 7 zeros.




arrays