Jak znaleźć sumę tablicy liczb

808

Biorąc pod uwagę tablicę [1, 2, 3, 4], jak mogę znaleźć sumę jej elementów? (W tym przypadku suma byłaby 10.)

Myślałem, że $.eachmoże się przydać, ale nie jestem pewien, jak to zaimplementować.

akano1
źródło
4
To pytanie jest przedmiotem meta dyskusji
Ghost Madara
18
@ tereško Niechęć do Google nie jest ważnym bliskim powodem Stackoverflow. Proszę oddać głos, jeśli uważasz, że pytanie nie zostało dobrze (ponownie) przeszukane. (Sądząc również po odpowiedziach - wydaje się, że jest to bardzo kontrowersyjny temat z wieloma możliwymi rozwiązaniami, w tym z pewnymi wysoce uprzywilejowanymi złymi praktykami (ewaluacyjnymi) - zaskakująco.)
Trilarion
8
Uwaga: większość odpowiedzi tutaj jest obliczana a[0] + a[1] + ..., co może przekształcić się w konkatenację łańcuchów, jeśli tablica zawiera elementy nieliczbowe. Np ['foo', 42].reduce((a,b)=>a+b, 0) === "0foo42".
Beni Cherniavsky-Paskin
Nie ma wbudowanego reduktora, który można by przesłać do Array.reduce? Myślisz coś w stylu [1,2,3].reduce(Math.sum).
Phil

Odpowiedzi:

540

Zalecane (zmniejsz z wartością domyślną)

Array.prototype.reduce można wykorzystać do iteracji w tablicy, dodając bieżącą wartość elementu do sumy poprzednich wartości elementu.

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

Bez wartości domyślnej

Otrzymujesz TypeError

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

Przed funkcjami strzałek ES6

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

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

Dane nienumeryczne

Jeśli możliwe są dane nieparzyste, możesz sobie z tym poradzić?

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

Non-zalecany niebezpieczne użycie eval

Możemy użyć eval do wykonania ciągu reprezentującego kod JavaScript. Używając funkcji Array.prototype.join do konwersji tablicy na ciąg, zmieniamy [1,2,3] na „1 + 2 + 3”, co daje w wyniku wartość 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('+'))

Oczywiście wyświetlanie ostrzeżenia nie jest najgorszą rzeczą, jaka może się zdarzyć. Jedynym powodem, dla którego podałem to pytanie, jest odpowiedź na pytanie Ortunda, ponieważ nie sądzę, aby zostało wyjaśnione.

OwChallie
źródło
8
Czy wiesz, że ta magia reduce()jest nadal o 25-30% wolniejsza niż prosta indeksowana for()pętla po wielu latach? jsperf.com/reduce-vs-loop/4
tevemadar
Przy okazji ma to problemy, jeśli liczba wynosi „0” - z dowolnego powodu może zostać zinterpretowana jako ciąg. Dodanie 1 * a + 1 * b działało dla mnie. Jeśli chodzi o szybkość, łatwiej było pisać i nie dbam o szybkość
Peter Kay
1179

W Lisp to byłaby właśnie praca reduce. Zobaczysz ten rodzaj kodu:

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

Na szczęście w JavaScript też mamy reduce! Niestety +jest operatorem, a nie funkcją. Ale możemy zrobić to ładnie! Tutaj spójrz:

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

Czy to nie jest ładne? :-)

Nawet lepiej! Jeśli używasz ECMAScript 2015 (alias ECMAScript 6 ), może to być całkiem ładne:

const sum = [1, 2, 3].reduce((partial_sum, a) => partial_sum + a,0); 
console.log(sum); // 6
Florian Margaine
źródło
28
Zakładając, że wszyscy używamy ES2015, możemy sprawić, że będzie mniej gadatliwy:[1, 2, 3].reduce((a,b)=>a+b)
Denys Séguret
1
Zastanawiam się, czy czas wykonania redukcji za pomocą funkcji (a, b) jest porównywalny z ręczną iteracją i sumowaniem, czy też jest w tym jakiś znaczny narzut?
Trilarion
1
Uważam, że warto wspomnieć, że odpowiedź można znaleźć na podlinkowanej stronie: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
Alex Cohn
2
Do Array dodałbym kilka metod: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
@Black zmniejsza tablicę do pojedynczej wartości.
Florian Margaine
204

Dlaczego nie zmniejszyć? Zwykle jest to nieco sprzeczne z intuicją, ale użycie go do znalezienia kwoty jest dość proste:

var a = [1,2,3];
var sum = a.reduce(function(a, b) { return a + b; }, 0);
Casey Rodarmor
źródło
3
IE8 nie obsługuje tego i nie wygląda na to, że jQuery zamierza go dodać. Jednak Prototype ma to.
Ishmael Smyrnow
4
@ Ismael, możesz użyć UnderscoreJS, który wraca do implementacji przeglądarki, jeśli jest dostępna, lub implementuje własną w inny sposób.
Pablo Diaz
3
Co jest sprzeczne z intuicją reduce()?
kanon
3
@ s4nji Array.prototype.reduce() redukuje tablicę do pojedynczej wartości zwracanej.
kanon
6
@ s4nji ... chyba że redukujesz sos - w takim przypadku sprowadzasz go do jego podstawowych zasad, tj. sumy wszystkich smaków bez nadmiaru wody. :-)
CB Du Rietz
97
var arr = [1,2,3,4];
var total=0;
for(var i in arr) { total += arr[i]; }
Bursztyn
źródło
3
Jest to o wiele szybsze niż powyższe rozwiązanie jQuery.each ().
Wściekły Dan
41
@Sprog: Jednak korzystanie (var i=0; i<arr.length; i++)jest jeszcze szybsze. I nawet wtedy używanie var sum=0; var i=arr.length; while(i--) sum += arr[i]jest jeszcze szybsze.
Riking
14
Używanie for... inpętli na tablicach działa w tym przypadku _ przypadkowo_ i ponieważ tablice rozszerzają obiekty. Rozwiązanie Rikinga jest lepsze
Benjamin Gruenbaum,
2
@BenjaminGruenbaum pod warunkiem, że nic nie dodało wyliczalnych właściwości do prototypu tablicy ...
kanon
1
@YSC nie, nie ma. for...inPętla w JavaScript bierze indeksy, co jest częstą przeszkodą dla programistów, którzy oczekują, aby uzyskać wartości. (Spróbuj for(var i in [1,2,3]) { console.log(i); }w konsoli.)
Amber
61
var total = 0;
$.each(arr,function() {
    total += this;
});
Tyler Carter
źródło
87
Proszę, proszę, użyj reduceponiższej odpowiedzi ; nie deklaruj zmiennych zmiennych, gdy ich nie masz.
Bruno Grieder
9
Ta odpowiedź jest w trakcie meta dyskusji
Ghost Madara
11
Nie używaj tego, nawet jeśli jest to „zaakceptowana odpowiedź”; odpowiedź Floriana poniżej jest znacznie lepsza!
Andy Sinclair,
12
@BrunoGrieder „Nie deklaruj zmiennych zmiennych, gdy nie musisz” to wyjątkowo stronnicza opinia na temat imperatywnego języka , nie jest to zapach kodu jakimkolwiek fragmentem wyobraźni. Absolutnie nie ma nic złego w odpowiedzi Tylera, a jedyną różnicą między Tylerem a Florianem jest styl.
Rob
5
Z PO: Myślałem, że $ .each może być przydatny, ale nie jestem pewien, jak go wdrożyć. To może nie być najlepsze, ale odpowiedz na prośbę PO.
32

Jeśli używasz Lodash, możesz użyć funkcji sumowania

array = [1, 2, 3, 4];
sum = _.sum(array); // sum == 10
David mówi Przywróć Monikę
źródło
29

Jest to możliwe, zapętlając wszystkie elementy i dodając je przy każdej iteracji do sumzmiennej.

var array = [1, 2, 3];

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

JavaScript nie zna zakresu bloków, więc sumbędzie dostępny:

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

To samo co powyżej, ale opatrzone adnotacjami i przygotowane jako prosta funkcja:

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
źródło
12
Choć sprytny, kod deklarujący sumpoza pętlą jest znacznie bardziej czytelny.
Beni Cherniavsky-Paskin
@ BeniCherniavsky-Paskin Tak, to samo tutaj ... Nie wiem, dlaczego tego dnia zrobiłem w ten sposób ... Pozwolę jednak, że tak jest! To tylko przykład, jak moglibyśmy ... ;)
yckart
Od wersji ES6 skrypt javascript zna zakres blokowania za pomocą consti let. Możesz więc zadeklarować sumpoza forpętlą jako let sum = 0;. Możesz także buforować długość tablicy przed pętlą jakoconst length = array.length;
KSK
23
arr.reduce(function (a, b) {
    return a + b;
});

Odwołanie: Array.prototype.reduce ()

onhout
źródło
6
To się nie powiedzie, jeśli tak arrjest [].
7
Dodaj wartość domyślną, tak jak: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];

Zajmie to średnio 1,57 ms / przebieg (mierzone ponad 1000 przebiegów na tablicy 100 losowych liczb normalnych), w porównaniu do 3,604 ms / przebieg przy eval() zastosowaniu powyższej metody i 2,151 ms / przebieg ze standardem dla (i, długość, ++ ).

Uwaga dotycząca metodologii: ten test został przeprowadzony na serwerze Google Apps Script, więc ich silniki javascript są prawie takie same jak Chrome.

EDYCJA: --izamiast i--zapisuje 0,12 ms przy każdym uruchomieniu (i-- wynosi 1,7)

EDYCJA: Święty przekleństwo, nie wspominając o tym całym poście. Użyj wyżej wspomnianej metody redukcji (), to tylko 1 ms / przebieg.

Riking
źródło
1
Uwielbiam używane czasy. Twoja odpowiedź nie mówi tylko „Wybierz mnie, jestem najlepszy!” Zamiast tego pokazuje nam dlaczego . W każdym razie while (--i) do_somethingmoże to działać również w przypadku innych rzeczy.
Programy Redwolf
var sum = arr[0]
noobninja
12

Możesz także użyć funkcji zmniejszania prawa.

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

co daje wynik jako 21.

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

Rohit Bhalke
źródło
Powinno być szybsze w chrome, ponieważ optymalizację do zapętlania javascript (tj. Zmniejszanie długości) można również zastosować do bazowego zestawu, aby przyspieszyć jego działanie.
Jack Giffin,
12

Ktoś szuka funkcjonalnego onelinera takiego jak ja? Weź to:

sum= arr.reduce(function (a, b) {return a + b;}, 0);
geek-merlin
źródło
Możesz dodać wartość początkową redukcji jako drugi parametr:arr.reduce(function(a, b) { return a + b;}, 0);
Ngz
Dzięki! włączę to.
geek-merlin
12

Zabawne podejście:

eval([1,2,3].join("+"))
elektron
źródło
5
Czy możesz rozwinąć tę odpowiedź, wyjaśniając, co dzieje się w tym kodzie? Dlaczego to działa? Co to dokładnie robi? Te rzeczy pomagają poprawić jakość odpowiedzi.
Ortund
@ user40521 już odpowiedział na to tak, jak myślę. Nie widziałem tego
elektron
Chociaż jest krótki i słodki, a na pewno interesujący, jest również bardzo nieefektywny. Używanie reducejest zdecydowanie lepsze w większości, jeśli nie we wszystkich przypadkach.
Ninjakannon
Errm,[1,"2;YourProgram.ripToShreds();3",4]
Programy Redwolf
Więc dostaję, NaNgdy próbuję eval(['alert("removing your computer")',2,3].join("+"))złą odpowiedź 0/10
pie6k
12

OK, wyobraź sobie, że masz tę tablicę poniżej:

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

Zacznijmy szukać na wiele różnych sposobów aby to zrobić, ponieważ nie mogłem znaleźć tutaj wyczerpującej odpowiedzi:

1) Korzystanie z wbudowanej funkcji zmniejszania ()

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

2) Korzystanie z pętli 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) Używanie pętli while

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

4) Korzystanie z tablicy forEach

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

i nazwij to tak:

total(arr); //return 10

Nie zaleca się prototypowania czegoś takiego do Array ...

Alireza
źródło
10

Standardowe rozwiązanie JavaScript:

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 */

To działa dla mnie (wynik powinien wynosić 5). Mam nadzieję, że w tego rodzaju rozwiązaniu nie ma ukrytej wady.

nano
źródło
1
Ponadto każdy programista C lub Java byłby w stanie to zrozumieć.
Audrius Meskauskas,
w prostym celu zsumowania wszystkich wartości prosty zwykły for for loop nie ma żadnych rywali pod względem czasu wykonania
fedeghe
Jedynym problemem jest to, że jest trochę denerwujące, gdy masz 20 na wszystkie pętle zagnieżdżone w sobie
Redwolf Programs
7
var totally = eval(arr.join('+'))

W ten sposób możesz umieścić w tablicy wszystkie egzotyczne rzeczy.

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

Żartuję tylko do połowy.

użytkownik40521
źródło
26
Na wpół się śmieję
kauc
eval(['alert("removing your computer")',2,3].join("+"))
pie6k
7

Jestem początkującym w JavaScript i kodowaniu, ale odkryłem, że prosty i łatwy sposób sumowania liczb w tablicy wygląda następująco:

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

Zasadniczo chciałem się do tego przyczynić, ponieważ nie widziałem wielu rozwiązań, które nie używają wbudowanych funkcji, a ta metoda jest łatwa do napisania i zrozumienia.

CandyPaintedRIMS
źródło
1
Czym różni się to od tej odpowiedzi z 2012 r. Lub tej z 2014 r. ? Istnieją dwa rozwiązania, których nie widziałeś.
Dan Dascalescu
5

Krótki fragment kodu JavaScript wykona tę pracę:

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 Żilenkow
źródło
5

Kilka osób zasugerowało dodanie .sum()metody do Array.prototype. Jest to ogólnie uważane za złą praktykę, więc nie sugeruję, abyś to zrobił.

Jeśli nadal nalegasz na zrobienie tego, to jest to zwięzły sposób napisania:

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

następnie: [1,2].sum(); // 3

Zauważ, że funkcja dodana do prototypu używa kombinacji funkcji ES5 i ES6 oraz składni strzałek. functionJest uznana metoda pozwoli uzyskać thiskontekst przeprowadzoną Arrayże jesteś działających na. Użyłem =>zwięzłości w trakcie reducerozmowy.

Chłopak
źródło
5

Użyj forpętli:

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

Lub nawet forEachpętlę:

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

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

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

Dla uproszczenia użyj 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
źródło
4

Nie musisz initial value! Ponieważ jeśli nie initial valuezostanie przekazane, callback functionnie zostanie wywołane na pierwszym elemencie listy, a pierwszy element zostanie przekazany jako initial value. Very c OO l funkcja :)

[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
Tak
źródło
4

Oto eleganckie jedno-liniowe rozwiązanie wykorzystujące algorytm stosu , choć zrozumienie piękna tej implementacji może trochę potrwać.

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

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

Zasadniczo funkcja przyjmuje tablicę i sprawdza, czy tablica zawiera dokładnie jeden element. Jeśli false, wyskakuje ostatni element ze stosu i zwraca zaktualizowaną tablicę.

Piękno tego fragmentu polega na tym, że funkcja obejmuje arr[0]sprawdzanie, aby zapobiec nieskończonemu zapętleniu. Gdy osiągnie ostatni element, zwraca całą sumę.

Rex Low
źródło
4

Możesz połączyć metodę redukcyjną () z wyrażeniem lambda:

[1, 2, 3, 4].reduce((accumulator, currentValue) => accumulator + currentValue);
antonjs
źródło
3

Posługiwać się reduce

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

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

console.log(sum);

Damien Asseya
źródło
3

widziałem wszystkie odpowiedzi dotyczące rozwiązania „zmniejszającego”

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
źródło
3

Precyzja

Sortuj tablicę i sumę początkową od najmniejszych liczb (fragment pokazuje różnicę w przypadku braku sortowania)

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

Do wielowymiarowej tablicy liczb użyj arr.flat(Infinity)

Kamil Kiełczewski
źródło
2

Fajne sztuczki tutaj, mam niezły wybór z wieloma bezpiecznymi tradycyjnymi odpowiedziami, które nie buforują długości tablicy.

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

Bez buforowania długości tablicy kompilator JS musi przechodzić przez tablicę przy każdej iteracji pętli, aby obliczyć długość, w większości przypadków jest to niepotrzebne obciążenie. V8 i wiele współczesnych przeglądarek optymalizuje to dla nas, więc nie było to tak ważne, ale istnieją starsze urządzenia, które korzystają z tego prostego buforowania.

Jeśli długość może ulec zmianie, buforowanie może spowodować nieoczekiwane skutki uboczne, jeśli nie wiesz, dlaczego buforujesz długość, ale dla funkcji wielokrotnego użytku, której jedynym celem jest wzięcie tablicy i dodanie wartości razem, jest to świetne dopasowanie.

Oto link CodePen dla tej funkcji arraySum. http://codepen.io/brandonbrule/pen/ZGEJyV

Możliwe, że jest to przestarzały sposób myślenia, który utkwił we mnie, ale nie widzę wady korzystania z niego w tym kontekście.

Brandon Brule
źródło
Problem buforowania długości to czerwony śledź. Silniki JS zoptymalizują to dla Ciebie bez mrugnięcia okiem.
2

To są naprawdę świetne odpowiedzi, ale na wszelki wypadek, jeśli liczby są po kolei, jak w pytaniu (1,2,3,4), możesz to łatwo zrobić, stosując wzór (n * (n + 1)) / 2 gdzie n jest ostatnią liczbą

Santosh
źródło
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
źródło
Czy ten kod usuwa Twój system operacyjny? Czy też wysyła mi twoje dane osobowe?
2

To jest o wiele łatwiejsze

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
źródło
2

Prosty przykład metody:

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
źródło