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ć.


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.


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

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

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

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

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.


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

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


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.


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

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

sum= arr.reduce(function (a, b) {return a + b;}, 0);

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("+"))

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


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.


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.


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.


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)

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.


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

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

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ę.


4

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

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


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)

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)


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.


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ą


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

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)

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]));
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.