Bir sayı dizisinin toplamını bulma


808

Bir dizi verildiğinde [1, 2, 3, 4], öğelerinin toplamını nasıl bulabilirim? (Bu durumda, toplam olacaktır 10.)

$.eachYararlı olabileceğini düşündüm , ancak nasıl uygulanacağından emin değilim.



18
@ tereško Google'a isteksizlik Stackoverflow'da geçerli bir kapanış nedeni değil. Sorunun iyi (yeniden) aranmadığını düşünüyorsanız lütfen oy verin. (Ayrıca cevaplara bakılırsa - bu, son derece yükselen bazı kötü uygulamalar da dahil olmak üzere birçok olası çözümle son derece tartışmalı bir konu gibi görünüyor (eval) - şaşırtıcı bir şekilde.)
Trilarion

8
Not: Buradaki yanıtların çoğu esasen hesaplama yapar a[0] + a[1] + ..., bu da dizinin sayı olmayan elemanları varsa dize birleştirmesine dönüşebilir. Örn ['foo', 42].reduce((a,b)=>a+b, 0) === "0foo42".
Beni Cherniavsky-Paskin

Array.reduce'a beslenebilecek yerleşik bir redüktör yok mu? Gibi bir şey düşünmek [1,2,3].reduce(Math.sum).
Phil

Yanıtlar:


543

Önerilen (varsayılan değerle azaltma)

Array.prototype.reduce , dizi boyunca yineleme yapmak için kullanılabilir ve geçerli öğe değerini önceki öğe değerlerinin toplamına ekler.

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

Varsayılan değer olmadan

TypeError alıyorsunuz

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

ES6'nın ok işlevlerinden önce

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

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

Sayı olmayan girişler

Sayı olmayan girişler varsa, bunu ele almak isteyebilirsiniz?

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

Tavsiye edilmeyen tehlikeli değerlendirme kullanımı

Eval kodunu JavaScript kodunun dize olarak temsilini yürütmek için kullanabiliriz . Diziyi bir dizeye dönüştürmek için Array.prototype.join işlevini kullanarak [1,2,3] değerini 6 olarak değerlendirilen "1 + 2 + 3" olarak değiştiririz.

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

Elbette bir uyarı görüntülemek, olabilecek en kötü şey değildir. Bunu dahil etmemin tek nedeni Ortund'un sorusuna netleştirildiğini düşünmediğim için sorudur.


8
Bu büyünün uzun yıllar sonra reduce()basit bir indeksli for()döngüden hala% 25-30 daha yavaş olduğunu biliyor musunuz ? jsperf.com/reduce-vs-loop/4
tevemadar

Bu arada sayı "0" ise sorunlara yol açar - herhangi bir nedenle dize olarak yorumlanabilir. 1 * a + 1 * b eklemek benim için çalıştı. Hız gelince, bu yazmak daha kolay ve hız umurumda değil
Peter Kay

1179

In Lisp için tam bir iş olabilir iyiyerin reduce. Bu tür bir kod görürsünüz:

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

Neyse ki, JavaScript'te de var reduce! Ne yazık ki, +bir işleç değil, bir işleçtir. Ama güzel yapabiliriz! İşte bak:

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

Güzel değil mi? :-)

Daha iyi! ECMAScript 2015 (diğer adıyla ECMAScript 6 ) kullanıyorsanız, bu güzel olabilir:

const sum = [1, 2, 3].reduce((partial_sum, a) => partial_sum + a,0); 
console.log(sum); // 6

28
Hepimizin ES2015 kullandığımızı varsayarsak, daha az ayrıntılı yapabiliriz:[1, 2, 3].reduce((a,b)=>a+b)
Denys Séguret

1
Bir işlevle (a, b) azaltılma yürütme süresinin manuel yineleme ve toplamla karşılaştırılabilir olup olmadığını veya bazı önemli ek yükler olup olmadığını merak ediyorum.
Trilarion

1
Cevabın aslında bağlantı verdiğiniz sayfada bulunabileceğini belirtmek isterim: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Alex Cohn

2
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; }
Array'a

2
@Siyah bir diziyi tek bir değere düşürür.
Florian Margaine

205

Neden azaltmıyorsunuz? Genellikle biraz sezgiseldir, ancak bir miktar bulmak için kullanmak oldukça basittir:

var a = [1,2,3];
var sum = a.reduce(function(a, b) { return a + b; }, 0);

3
IE8 desteklemiyor ve jQuery eklemeyi planlıyor gibi görünmüyor. Ancak, Prototip buna sahiptir.
Ishmael Smyrnow

4
@Ishmael, varsa tarayıcının uygulamasına geri dönen veya aksi takdirde kendi uygulayan UnderscoreJS'yi kullanabilirsiniz.
Pablo Diaz

3
Karşı sezgisel olan nedir reduce()?
Canon

3
@ s4nji bir diziyi tek bir dönüş değerine Array.prototype.reduce() düşürür .
Canon

6
@ s4nji ... bir sosu azaltmadığınız sürece - bu durumda, temeline, yani su ek yükü olmadan tüm lezzetlerin toplamına vidalıyorsunuz. :-)
CB Du Rietz

97
var arr = [1,2,3,4];
var total=0;
for(var i in arr) { total += arr[i]; }

3
Bu, yukarıdaki jQuery.each () çözümünden çok daha hızlıdır.
Angry Dan

41
@Sprog: Bununla birlikte, (var i=0; i<arr.length; i++)kullanımı daha da hızlıdır. Ve o zaman bile, var sum=0; var i=arr.length; while(i--) sum += arr[i]kullanımı daha da hızlı.
Riking

14
for... inDizilerde döngüler kullanmak bu durumda _ tesadüfen_ çalışır ve diziler nesneleri genişletir. Riking'in çözümü daha iyi
Benjamin

2
@BenjaminGruenbaum, hiçbir şeyin dizinin prototipine numaralandırılabilir özellikler eklememesi koşuluyla ...
canon

1
@ YSC hayır, öyle değil. for...inJavaScript'teki bir döngü, değerleri almayı bekleyen kodlayıcılar için ortak bir engel olan endeksleri alır. ( for(var i in [1,2,3]) { console.log(i); }Bir konsolda deneyin .)
Amber

61
var total = 0;
$.each(arr,function() {
    total += this;
});

87
Lütfen, lütfen, lütfen reduceaşağıdaki cevabı kullanın ; sizde yok mutable değişebilir beyan etmeyin.
Bruno Grieder


11
"Kabul edilen cevap" olmasına rağmen lütfen bunu kullanmayın; Florian'ın cevabı çok daha iyi!
Andy Sinclair

12
@BrunoGrieder "Zorunlu olmayan değişkenleri beyan etmek zorunda değilsiniz" zorunlu bir dil hakkında son derece önyargılı bir fikirdir , hayal gücünün herhangi bir uzantısıyla neredeyse bir kod kokusu değildir. Tyler'ın cevabında kesinlikle yanlış bir şey yoktur ve Tyler'ın ve Florian'ın arasındaki tek fark üsluptur.
Rob

5
OP'den : $ .each'in yararlı olabileceğini düşündüm, ancak nasıl uygulanacağından emin değilim. Bu belki de en iyisi olmayabilir, ancak OP'nin isteğine cevap verin.


29

Bu, tüm öğelerin üzerine döngü sumyapıp her yinelemeye değişken bir değişken ekleyerek mümkündür .

var array = [1, 2, 3];

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

JavaScript blok kapsamayı bilmiyor, bu nedenle sumerişilebilir olacak:

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

Yukarıdaki açıklama ile aynı, ancak açıklamalı ve basit bir fonksiyon olarak hazırlanmıştır:

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
Akıllı olsa da sum, döngü dışında okunabilir kod çok daha okunaklı bulurdum .
Beni Cherniavsky-Paskin

@ BeniCherniavsky-Paskin Evet, burada da aynı ... O gün neden böyle yaptığımı bilmiyorum ... Ancak, olduğu gibi izin vereceğim! Bu nasıl yapabileceğimize sadece bir örnek ... ;)
yckart

ES6'dan beri javascript constve ile blok kapsamayı biliyor let. Böylece döngünün sumdışında forolarak ilan edebilirsiniz let sum = 0;. Ayrıca dizi uzunluğunu döngüden önce önbelleğe alabilirsinizconst length = array.length;
KSK

23
arr.reduce(function (a, b) {
    return a + b;
});

Referans: Array.prototype.reduce ()


6
Bu başarısız olur arrise [].

7
Bunun gibi varsayılan bir değer ekleyin: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];

Bu, eval()yukarıdaki yöntemle 3.604 ms / çalışma ve standart (i, uzunluk, ++ ) döngü.

Metodoloji notu: Bu test bir Google Apps Script sunucusunda gerçekleştirildi, bu nedenle javascript motorları Chrome ile hemen hemen aynı.

DÜZENLEME: --iyerine i--0.12 ms her çalışmanın (ben- 1.7 olan) kaydeder

EDIT: Kutsal expletive, tüm bu yazı boş ver. Yukarıda belirtilen reduce () yöntemini kullanın, sadece 1 ms / çalışma.


1
Kullandığınız zamanlamaları seviyorum. Cevabınız sadece "Beni seçin, en iyisiyim" demek değildir. Bunun yerine bize nedenini gösterir . Her neyse, while (--i) do_somethingbaşka şeyler için de işe yarayabilir.
Redwolf Programları

var sum = arr[0]
noobninja


12

Benim gibi işlevsel bir oneliner arayan var mı? Bunu al:

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

İkinci parametre olarak azaltmak için bir başlangıç ​​değeri ekleyebilirsiniz:arr.reduce(function(a, b) { return a + b;}, 0);
Ngz

Teşekkürler! Bunu dahil edeceğim.
geek-merlin

12

Komik yaklaşım:

eval([1,2,3].join("+"))

5
Lütfen bu kodda neler olduğunu açıklayarak bu cevabı genişletebilir misiniz? Neden çalışıyor? Tam olarak ne yapar? Bu şeyler cevabın kalitesini artırmaya yardımcı olur.
Ortund

@ user40521 bence bu zaten cevap verdi. Görmedim.
elektron

Bu kısa ve tatlı ve kesinlikle ilginç olsa da, aynı zamanda çok verimsiz. reduceHepsi olmasa da çoğunluk için kullanmak kesinlikle tercih edilir.
Ninjakannon

Errm,[1,"2;YourProgram.ripToShreds();3",4]
Redwolf Programları

Yani yanlış cevap NaNdenerken alıyorum eval(['alert("removing your computer")',2,3].join("+"))0/10
pie6k

12

Tamam, aşağıda bu diziye sahip olduğunuzu düşünün:

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

Çok farklı yollara bakmaya başlayalımBurada kapsamlı bir cevap bulamadığım için bunu :

1) Dahili azaltma () kullanma

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

2) Döngü için kullanma

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) while döngüsü kullanma

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

4) Her diziyi kullanma

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

ve şöyle deyin:

total(arr); //return 10

Array'a böyle bir şey prototiplemeniz önerilmez ...


10

Standart bir JavaScript çözümü:

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

Bu benim için çalışıyor (sonuç 5 olmalı). Umarım bu tür bir çözümde gizli bir dezavantaj yoktur.


1
Ayrıca, herhangi bir C veya Java programcısı bunu anlayabilir.
Audrius Meskauskas

tüm değerleri özetlemenin basit amacı için, döngü için basit
düzün

Tek sorun, birbirlerine iç içe döngüler için 20 olduğunda biraz sinir bozucu
Redwolf Programları

7
var totally = eval(arr.join('+'))

Bu şekilde diziye her türlü egzotik şeyi koyabilirsiniz.

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

Ben sadece şaka yapıyorum.


26
Yarı gülüyorum
caub

eval(['alert("removing your computer")',2,3].join("+"))
pie6k

7

Ben genel olarak JavaScript ve kodlama ile bir acemi değilim, ama bir dizideki sayıları toplamak için basit ve kolay bir yol şöyle:

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

Temel olarak, buna katkıda bulunmak istedim çünkü yerleşik işlevleri kullanmayan birçok çözüm görmedim ve bu yöntemin yazılması ve anlaşılması kolaydır.


1
Bu, 2012 yanıtından veya 2014 yanıtından farkı nedir? Görmediğiniz iki çözüm var.
Dan Dascalescu

5

Kısa bir JavaScript kodu parçası bu işi yapar:

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

Birkaç kişi için bir .sum()yöntem eklemeyi önerdi Array.prototype. Bu genellikle kötü uygulama olarak kabul edilir, bu yüzden bunu yapmanızı önermiyorum.

Hala yapmakta ısrar ediyorsanız, bu yazmanın kısa bir yoludur:

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

sonra: [1,2].sum(); // 3

Prototipe eklenen işlevin ES5 ve ES6 işlevi ile ok sözdiziminin bir karışımını kullandığını unutmayın. functionYöntem almak için izin bildirildi thisgelen bağlam Arrayüzerinde çalışan olduğunuzu. Çağrı =>içinde kısalık için kullandım reduce.


5

Bir fordöngü kullanın :

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

Veya bir forEachdöngü bile :

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

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

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

Basitlik için reduceşunları kullanın :

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

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

4

Gerek yok initial value! Çünkü hayır initial valueiletilirse, callback functionlistenin ilk öğesinde çağrılmaz ve ilk öğenin yerine initial value. Çok c OO l özelliği :)

[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

İşte yığın algoritması kullanan zarif bir tek katmanlı çözüm , ancak bu uygulamanın güzelliğini anlamak biraz zaman alabilir.

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

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

Temel olarak, işlev bir diziyi kabul eder ve dizinin tam olarak bir öğe içerip içermediğini kontrol eder. False olursa, son öğeyi yığının dışına çıkar ve güncellenmiş diziyi döndürür.

Bu pasajın güzelliği, fonksiyonun arr[0]sonsuz döngüyü önlemek için kontrol içermesidir . Son öğeye ulaştığında, toplamın tamamını döndürür.


4

Reduce () yöntemini lambda ifadesi ile birleştirebilirsiniz:

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


3

tüm cevapları 'azaltmak' çözümü için gidiş gördüm

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

3

doğruluk

Diziyi sıralama ve toplamı en küçük sayılardan başlatma (snippet, nonsort ile farkı gösterir)

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

Çok boyutlu sayı dizisi için arr.flat(Infinity)


2

Burada harika hileler, dizinin uzunluğunu önbelleğe almayan güvenli geleneksel cevapların birçoğuyla bir nit seçimim var.

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

Dizinin uzunluğunu önbelleğe almadan JS derleyicisinin uzunluğu hesaplamak için döngünün her yinelemesiyle diziden geçmesi gerekir, çoğu durumda gereksiz yük. V8 ve birçok modern tarayıcı bunu bizim için optimize ediyor, bu yüzden daha az endişe duyuyor, ancak bu basit önbelleklemeden yararlanan eski cihazlar var.

Uzunluk değişebilirse, uzunluğu neden önbelleğe aldığınızı bilmiyorsanız bazı beklenmedik yan etkilere neden olabilecek önbellekleme, ancak tek kullanımlık bir işlev için tek amacı bir dizi alıp değerleri bir araya getirmek mükemmel uyum.

İşte bu arraySum işlevi için bir CodePen bağlantısı. http://codepen.io/brandonbrule/pen/ZGEJyV

Bu, bana yapışmış, modası geçmiş bir zihniyet olabilir, ancak bu bağlamda kullanmanın bir dezavantajı görmüyorum.


Uzunluğun önbelleğe alınması sorunu kırmızı bir ringa balığıdır. JS motorları yanıp sönmeden bunu sizin için optimize eder.

2

Bunlar gerçekten harika cevaplar, ancak sayıların sorudaki gibi olması durumunda (1,2,3,4) bunu (n * (n + 1)) / 2 formülünü uygulayarak kolayca yapabilirsiniz. n son sayıdır


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

Bu kod işletim sisteminizi kaldırıyor mu? Yoksa kişisel bilgilerinizi bana mı gönderiyor?

2

Bu çok daha kolay

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

Basit bir yöntem örneği:

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]));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.