Como encontrar a soma de uma matriz de números

809

Dada uma matriz [1, 2, 3, 4], como posso encontrar a soma de seus elementos? (Nesse caso, a soma seria 10.)

Eu pensei que $.eachpoderia ser útil, mas não tenho certeza de como implementá-lo.

akano1
fonte
4
Esta questão está em metat Discussão
Madara's Ghost
18
@ tereško A falta de vontade para com o Google não é um motivo próximo válido no Stackoverflow. Voto negativo se você achar que a pergunta não foi bem (re) pesquisada. (Também a julgar pelas respostas - este parece ser um tema muito controverso, com muitas soluções possíveis, incluindo algumas práticas altamente upvoted ruins (eval) -. Surpreendentemente)
Trilarion
8
Nota: a maioria das respostas aqui basicamente calcula a[0] + a[1] + ..., que pode se transformar em concatenação de strings se a matriz tiver elementos não numéricos. Por exemplo ['foo', 42].reduce((a,b)=>a+b, 0) === "0foo42".
Beni Cherniavsky-Paskin
Nenhum redutor embutido poderia alimentar Array.reduce? Pensando algo parecido [1,2,3].reduce(Math.sum).
Phil

Respostas:

545

Recomendado (reduzir com valor padrão)

Array.prototype.reduce pode ser usado para iterar pela matriz, adicionando o valor atual do elemento à soma dos valores anteriores.

console.log(
  [1, 2, 3, 4].reduce((a, b) => a + b, 0)
)
console.log(
  [].reduce((a, b) => a + b, 0)
)

Sem valor padrão

Você recebe um TypeError

console.log(
  [].reduce((a, b) => a + b)
)

Antes das funções de seta do ES6

console.log(
  [1,2,3].reduce(function(acc, val) { return acc + val; }, 0)
)

console.log(
  [].reduce(function(acc, val) { return acc + val; }, 0)
)

Entradas não numéricas

Se não-números são possíveis entradas, você pode querer lidar com isso?

console.log(
  ["hi", 1, 2, "frog"].reduce((a, b) => a + b)
)

let numOr0 = n => isNaN(n) ? 0 : n

console.log(
  ["hi", 1, 2, "frog"].reduce((a, b) => 
    numOr0(a) + numOr0(b))
)

Uso de avaliação perigoso não recomendado

Podemos usar eval para executar uma representação em string do código JavaScript. Usando a função Array.prototype.join para converter a matriz em uma string, alteramos [1,2,3] para "1 + 2 + 3", que é avaliado em 6.

console.log(
  eval([1,2,3].join('+'))
)

//This way is dangerous if the array is built
// from user input as it may be exploited eg: 

eval([1,"2;alert('Malicious code!')"].join('+'))

É claro que exibir um alerta não é a pior coisa que poderia acontecer. A única razão pela qual incluí isso é como resposta à pergunta de Ortund, pois não acho que tenha sido esclarecida.

OwChallie
fonte
8
Você sabe que essa mágica reduce()ainda é 25 a 30% mais lenta que um simples for()loop indexado após longos anos? jsperf.com/reduce-vs-loop/4
tevemadar
Isso causa problemas se o número for "0", a propósito - pode ser interpretado como uma string, por qualquer motivo. Adicionar 1 * a + 1 * b funcionou para mim. Quanto à velocidade, isso foi mais fácil de escrever e eu não me importo com a velocidade
Peter Kay
1179

No Lisp , esse seria exatamente o trabalho reduce. Você veria esse tipo de código:

(reduce #'+ '(1 2 3)) ; 6

Felizmente, em JavaScript, também temos reduce! Infelizmente, +é um operador, não uma função. Mas podemos torná-lo bonito! Olhe aqui:

const sum = [1, 2, 3].reduce(add,0); // with initial value to avoid when the array is empty

function add(accumulator, a) {
    return accumulator + a;
}

console.log(sum); // 6

Isso não é bonito? :-)

Melhor ainda! Se você estiver usando o ECMAScript 2015 (também conhecido como ECMAScript 6 ), pode ser assim:

const sum = [1, 2, 3].reduce((partial_sum, a) => partial_sum + a,0); 
console.log(sum); // 6
Florian Margaine
fonte
28
Supondo que todos usemos o ES2015, podemos torná-lo menos detalhado:[1, 2, 3].reduce((a,b)=>a+b)
Denys Séguret
1
Gostaria de saber se o tempo de execução de reduzir com uma função (a, b) é comparável a uma iteração e somatória manual ou se há alguma sobrecarga considerável incluída?
Trilarion
1
Eu acredito que vale a pena mencionar que a resposta pode realmente ser encontrada na página que você ligado: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
Alex Cohn
2
Eu adicionaria alguns métodos ao Array:Array.prototype.sum = function() { return this.reduce((a,b) => a+b, 0); } Array.prototype.avg = function() { return this.reduce((a,b) => a+b, 0)/this.length; }
pilat 2/09/16
2
@Black reduz uma matriz em um único valor.
Florian Margaine 29/04
205

Por que não reduzir? Geralmente é um pouco contra-intuitivo, mas usá-lo para encontrar uma soma é bem direto:

var a = [1,2,3];
var sum = a.reduce(function(a, b) { return a + b; }, 0);
Casey Rodarmor
fonte
3
O IE8 não suporta e não parece que o jQuery pretenda adicioná-lo. No entanto, o Prototype possui.
Ishmael Smyrnow
4
@Ishmael, você pode usar o UnderscoreJS, que volta à implementação do navegador, se disponível, ou implementa o seu próprio.
Pablo Diaz
3
O que é contra-intuitivo reduce()?
canon
3
@ s4nji Array.prototype.reduce() reduz uma matriz para um único valor de retorno.
canon
6
@ s4nji ... a menos que você esteja reduzindo um molho - nesse caso, você está colocando tudo no essencial, ou seja, a soma de todos os sabores sem a sobrecarga da água. :-)
CB Du Rietz
97
var arr = [1,2,3,4];
var total=0;
for(var i in arr) { total += arr[i]; }
Âmbar
fonte
3
Isso é muito mais rápido que a solução jQuery.each () acima.
Angry Dan
41
@ Sprog: No entanto, o uso (var i=0; i<arr.length; i++)é ainda mais rápido. E mesmo assim, o uso var sum=0; var i=arr.length; while(i--) sum += arr[i]é ainda mais rápido.
Riking
14
O uso de for... inloops em matrizes funciona nesse caso _ coincidentemente_ e porque matrizes estendem objetos. A solução da Riking é melhor
Benjamin Gruenbaum
2
@BenjaminGruenbaum desde que nada tenha adicionado propriedades enumeráveis para protótipo de variedade ...
canon
1
@YSC não, não. Um for...inloop em JavaScript pega os índices, que é um obstáculo comum para os codificadores que esperam obter os valores. (Tente for(var i in [1,2,3]) { console.log(i); }em um console.)
Âmbar
61
var total = 0;
$.each(arr,function() {
    total += this;
});
Tyler Carter
fonte
87
Por favor, por favor, use a resposta reduceabaixo; não declare vars mutáveis ​​quando você não tiver também.
Bruno Grieder 27/02
9
Esta resposta está sob meta-discussão
Madara's Ghost
11
Por favor, não use isso, mesmo que seja a "resposta aceita"; a resposta de Florian abaixo é muito melhor!
Andy Sinclair
12
@BrunoGrieder "Não declare vars mutáveis ​​quando não for necessário" é uma opinião extremamente tendenciosa sobre uma linguagem imperativa ; dificilmente é um cheiro de código por qualquer extensão da imaginação. Não há absolutamente nada de errado com a resposta de Tyler, e a única diferença entre Tyler e Florian é o estilo.
Rob
5
Do OP: Eu pensei que $ .each poderia ser útil, mas não sei como implementá-lo. Talvez não seja o melhor, mas responda à solicitação do OP.
33

Se você estiver usando o Lodash, poderá usar a função soma

array = [1, 2, 3, 4];
sum = _.sum(array); // sum == 10
David diz Reinstate Monica
fonte
29

Isso é possível repetindo todos os itens e adicionando-os em cada iteração a uma sumvariável.

var array = [1, 2, 3];

for (var i = 0, sum = 0; i < array.length; sum += array[i++]);

O JavaScript não sabe o escopo do bloco, por isso sumserá acessível:

console.log(sum); // => 6

O mesmo que acima, porém anotado e preparado como uma função simples:

function sumArray(array) {
  for (
    var
      index = 0,              // The iterator
      length = array.length,  // Cache the array length
      sum = 0;                // The total amount
      index < length;         // The "for"-loop condition
      sum += array[index++]   // Add number on each iteration
  );
  return sum;
}
yckart
fonte
12
Embora seja inteligente, eu acho o código que declara sumfora do loop muito mais legível.
Beni Cherniavsky-Paskin
@ BeniCherniavsky-Paskin Sim, o mesmo aqui ... Não sei por que fiz dessa maneira naquele dia ... No entanto, vou deixar como está! É apenas um exemplo de como podemos poderia ... ;)
yckart
Desde o ES6, o javascript sabe o escopo do bloco com conste let. Então você pode declarar sumfora do forloop como let sum = 0;. Você também pode armazenar em cache o comprimento da matriz antes do loop comoconst length = array.length;
KSK 22/11
23
arr.reduce(function (a, b) {
    return a + b;
});

Referência: Array.prototype.reduce ()

onhout
fonte
6
Isso irá falhar se arrfor [].
7
Adicione um valor padrão, assim:arr.reduce(function (a, b) { return a + b; }, 0);
Ngz
15
// Given array 'arr'
var i = arr.length;
var sum = 0;
while (--i) sum += arr[i];

Isso levará em média 1,57 ms / corrida (medido em 1000 execuções em uma matriz de 100 números normais aleatórios), comparado a 3.604 ms / corrida com o eval()método acima e 2.151 ms / corrida com um padrão para (i, comprimento, ++ ) ciclo.

Observação sobre a metodologia: esse teste foi executado em um servidor de scripts do Google Apps, portanto, seus mecanismos javascript são praticamente os mesmos do Chrome.

EDIT: em --ivez de i--economiza 0,12 ms cada execução (i-- é 1,7)

Edição: Santo palavrão, não importa todo este post. Use o método reduzir () mencionado acima, é apenas 1 ms / corrida.

Riking
fonte
1
Eu amo os horários que você usou. Sua resposta não diz apenas "Escolha-me, eu sou o melhor!" Em vez disso, mostra-nos o porquê . De qualquer forma, while (--i) do_somethingpode funcionar para outras coisas também.
Redwolf Programs
var sum = arr[0]
noobninja
12

Você também pode usar o reduzaRight.

[1,2,3,4,5,6].reduceRight(function(a,b){return a+b;})

que resulta como 21.

Referência: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/ReduceRight

Rohit Bhalke
fonte
Deve ser mais rápido no chrome, porque a otimização do loop de javascript (ou seja, diminuindo o comprimento) também pode ser aplicada ao assembly subjacente para torná-lo mais rápido.
Jack Giffin
12

Alguém está procurando um oneliner funcional como eu? Pegue isso:

sum= arr.reduce(function (a, b) {return a + b;}, 0);
geek-merlin
fonte
Você pode adicionar um valor inicial para reduzir como o 2º parâmetro:arr.reduce(function(a, b) { return a + b;}, 0);
Ngz
Obrigado! eu vou incorporar isso.
geek-merlin
12

OK, imagine que você tenha esta matriz abaixo:

const arr = [1, 2, 3, 4];

Vamos começar a procurar várias maneiras diferentes de fazer isso, pois não encontrei nenhuma resposta abrangente aqui:

1) Usando redução interna ()

function total(arr) {
  if(!Array.isArray(arr)) return;
  return arr.reduce((a, v)=>a + v);
}

2) Usando o loop for

function total(arr) {
  if(!Array.isArray(arr)) return;
  let totalNumber = 0;
  for (let i=0,l=arr.length; i<l; i++) {
     totalNumber+=arr[i];
  }
  return totalNumber;
}

3) Usando o loop while

function total(arr) {
  if(!Array.isArray(arr)) return;
  let totalNumber = 0, i=-1;
  while (++i < arr.length) {
     totalNumber+=arr[i];
  }
  return totalNumber;
}

4) Usando a matriz forEach

function total(arr) {
  if(!Array.isArray(arr)) return;
  let sum=0;
  arr.forEach(each => {
    sum+=each;
  });
  return sum;
};

e chame assim:

total(arr); //return 10

Não é recomendável prototipar algo assim para o Array ...

Alireza
fonte
11

Abordagem engraçada:

eval([1,2,3].join("+"))
elétron
fonte
5
Você poderia expandir esta resposta explicando o que está acontecendo neste código? Por que isso funciona? O que isso faz exatamente? Essas coisas ajudam a melhorar a qualidade da resposta.
Ortund 21/10
@ user40521 já respondeu isso da maneira que penso. Eu não vi.
Electron
Embora seja curto e doce, e certamente interessante, também é muito ineficiente. reduceDefinitivamente, o uso é preferível para a maioria, se não todos, os casos.
Ninjakannon
Errm,[1,"2;YourProgram.ripToShreds();3",4]
Redwolf Programs
Estou NaNtentando ao eval(['alert("removing your computer")',2,3].join("+"))responder a resposta errada 0/10
pie6k 27/03/19
10

Uma solução JavaScript padrão:

var addition = [];
addition.push(2);
addition.push(3);

var total = 0;
for (var i = 0; i < addition.length; i++)
{
    total += addition[i];
}
alert(total);          // Just to output an example
/* console.log(total); // Just to output an example with Firebug */

Isso funciona para mim (o resultado deve ser 5). Espero que não exista desvantagem oculta nesse tipo de solução.

nano
fonte
1
Além disso, qualquer programador C ou Java seria capaz de entender isso.
Audrius Meskauskas
para o simples propósito de somar todos os valores simples e velho para o laço não tem rivais em termos de tempo de execução
fedeghe
O único problema é que é um pouco chato quando você tem 20 loops todos aninhados um no outro
RedWolf Programas
7
var totally = eval(arr.join('+'))

Dessa forma, você pode colocar todos os tipos de coisas exóticas na matriz.

var arr = ['(1/3)','Date.now()','foo','bar()',1,2,3,4]

Estou apenas brincando.

user40521
fonte
26
Eu estou meio rindo
caub
eval(['alert("removing your computer")',2,3].join("+"))
pie6k
7

Sou iniciante em JavaScript e codificação em geral, mas descobri que uma maneira simples e fácil de somar os números em uma matriz é assim:

    var myNumbers = [1,2,3,4,5]
    var total = 0;
    for(var i = 0; i < myNumbers.length; i++){
        total += myNumbers[i];
    }

Basicamente, eu queria contribuir com isso porque não encontrei muitas soluções que não usem funções internas, e esse método é fácil de escrever e entender.

CandyPaintedRIMS
fonte
1
Como isso difere desta resposta de 2012 ou de 2014 ? Existem duas soluções que você não viu.
Dan Dascalescu
5

Um pequeno pedaço de código JavaScript faria este trabalho:

var numbers = [1,2,3,4];
var totalAmount = 0;

for (var x = 0; x < numbers.length; x++) {

    totalAmount += numbers[x];
}

console.log(totalAmount); //10 (1+2+3+4)
Timur Zhilenkov
fonte
5

Algumas pessoas sugeriram adicionar um .sum()método ao Array.prototype. Isso geralmente é considerado uma prática ruim, então não estou sugerindo que você faça isso.

Se você ainda insistir em fazê-lo, esta é uma maneira sucinta de escrevê-lo:

Array.prototype.sum = function() {return [].reduce.call(this, (a,i) => a+i, 0);}

então: [1,2].sum(); // 3

Observe que a função adicionada ao protótipo está usando uma mistura da função ES5 e ES6 e sintaxe da seta. O functioné declarado para permitir que o método obtenha o thiscontexto a partir do Arrayqual você está operando. Eu usei a =>brevidade dentro da reduceligação.

Cara
fonte
5

Use um forloop:

const array = [1, 2, 3, 4];
let result = 0;

for (let i = 0; i < array.length - 1; i++) {
  result += array[i];
}

console.log(result); // Should give 10

Ou até um forEachloop:

const array = [1, 2, 3, 4];
let result = 0;

array.forEach(number => {
  result += number;
})

console.log(result); // Should give 10

Para simplificar, use reduce:

const array = [10, 20, 30, 40];
const add = (a, b) => a + b
const result = array.reduce(add);

console.log(result); // Should give 100
JuicY_Burrito
fonte
4

Não precisa initial value! Porque se não initial valuefor passado, ele callback functionnão será chamado no primeiro elemento da lista e o primeiro elemento será passado como o initial value. Very c OO l feature :)

[1, 2, 3, 4].reduce((a, x) => a + x) // 10
[1, 2, 3, 4].reduce((a, x) => a * x) // 24
[1, 2, 3, 4].reduce((a, x) => Math.max(a, x)) // 4
[1, 2, 3, 4].reduce((a, x) => Math.min(a, x)) // 1
Yas
fonte
4

Aqui está uma solução elegante de uma linha que usa o algoritmo de pilha , embora possa levar algum tempo para entender a beleza dessa implementação.

const getSum = arr => (arr.length === 1) ? arr[0] : arr.pop() + getSum(arr);

getSum([1, 2, 3, 4, 5]) //15

Basicamente, a função aceita uma matriz e verifica se a matriz contém exatamente um item. Se falso, ele remove o último item da pilha e retorna a matriz atualizada.

A beleza desse snippet é que a função inclui a arr[0]verificação para evitar loop infinito. Quando atinge o último item, ele retorna a soma inteira.

Rex Low
fonte
4

Você pode combinar o método reduzem () com a expressão lambda:

[1, 2, 3, 4].reduce((accumulator, currentValue) => accumulator + currentValue);
antonjs
fonte
3

Usar reduce

let arr = [1, 2, 3, 4];

let sum = arr.reduce((v, i) => (v + i));

console.log(sum);

Damien Asseya
fonte
3

eu vi todas as respostas indo para a solução 'reduzir'

var array = [1,2,3,4]
var total = 0
for (var i = 0; i < array.length; i++) {
    total += array[i]
}
console.log(total)
Adrian Swifter
fonte
3

Precisão

Classifique a matriz e inicie a soma dos menores números (o snippet mostra a diferença com a não classificação)

[...arr].sort((a,b)=>a-b).reduce((a,c)=>a+c,0)

Para matriz multidimensional de números, use arr.flat(Infinity)

Kamil Kiełczewski
fonte
2

Truques legais aqui, eu tenho uma escolha nítida com muitas das respostas tradicionais seguras que não armazenam em cache o comprimento da matriz.

function arraySum(array){
  var total = 0,
      len = array.length;

  for (var i = 0; i < len; i++){
    total += array[i];
  }

  return total;
};

var my_array = [1,2,3,4];

// Returns 10
console.log( arraySum( my_array ) );

Sem armazenar em cache o comprimento da matriz, o compilador JS precisa percorrer a matriz com todas as iterações do loop para calcular o comprimento; na maioria dos casos, é uma sobrecarga desnecessária. A V8 e muitos navegadores modernos otimizam isso para nós, por isso é menos preocupante do que era, mas existem dispositivos mais antigos que se beneficiam desse cache simples.

Se o comprimento estiver sujeito a alterações, o armazenamento em cache poderá causar efeitos colaterais inesperados, se você não souber por que está armazenando o tamanho em cache, mas para uma função reutilizável cujo único objetivo é pegar uma matriz e adicionar os valores juntos, é um ótimo ajuste.

Aqui está um link CodePen para esta função arraySum. http://codepen.io/brandonbrule/pen/ZGEJyV

É possível que essa seja uma mentalidade desatualizada que esteja presa a mim, mas não vejo uma desvantagem em usá-la nesse contexto.

Brandon Brule
fonte
A questão do armazenamento em cache do comprimento é um arenque vermelho. Os mecanismos JS otimizarão isso para você sem piscar.
2

Essas são realmente ótimas respostas, mas, se os números estiverem em sequência, como na pergunta (1,2,3,4), você poderá fazer isso facilmente aplicando a fórmula (n * (n + 1)) / 2 em que n é o último número

Santosh
fonte
2
Object.defineProperty(Object.prototype, 'sum', {
    enumerable:false,
    value:function() {
        var t=0;for(var i in this)
            if (!isNaN(this[i]))
                t+=this[i];
        return t;
    }
});

[20,25,27.1].sum()                 // 72.1
[10,"forty-two",23].sum()          // 33
[Math.PI,0,-1,1].sum()             // 3.141592653589793
[Math.PI,Math.E,-1000000000].sum() // -999999994.1401255

o = {a:1,b:31,c:"roffelz",someOtherProperty:21.52}
console.log(o.sum());              // 53.519999999999996
ostranenie
fonte
Esse código remove seu sistema operacional? Ou ele envia suas informações pessoais para mim?
2

Isso é muito mais fácil

function sumArray(arr) {
    var total = 0;
    arr.forEach(function(element){
        total += element;
    })
    return total;
}

var sum = sumArray([1,2,3,4])

console.log(sum)
Jakub Gawel
fonte
2

Um exemplo simples de método:

function add(array){
    var arraylength = array.length;
    var sum = 0;
    for(var timesToMultiply = 0; timesToMultiply<arraylength; timesToMultiply++){
        sum += array[timesToMultiply];
    }

    return sum;
}

console.log(add([1, 2, 3, 4]));
Sifiso Nkabinde
fonte