Як знайти суму масиву чисел


808

Як дано масив [1, 2, 3, 4], як я можу знайти суму його елементів? (У цьому випадку сума була б 10.)

Я думав, що $.eachможе бути корисним, але я не знаю, як це здійснити.


4
Це питання знаходиться під мета дискусією
Привид

18
@ tereško Небажання google не є вагомою причиною для Stackoverflow. Будь ласка, підкресліть, якщо ви вважаєте, що питання недостатньо (пере) шукано. (Також судячи з відповідей - це, здається, є дуже суперечливою темою з багатьма можливими рішеннями, в тому числі з деякими висококваліфікованими поганими практиками (eval) - напрочуд.)
Trilarion

8
Примітка: більшість відповідей тут по суті є обчисленнями a[0] + a[1] + ..., які можуть перетворитись у конкатенацію рядків, якщо масив містить нечислові елементи. Напр ['foo', 42].reduce((a,b)=>a+b, 0) === "0foo42".
Бені Чернявський-Паскін

Жоден вбудований редуктор не міг би подати до Array.reduce? Думаючи щось на кшталт [1,2,3].reduce(Math.sum).
Філ

Відповіді:


540

Рекомендовано (зменшити за замовчуванням)

Array.prototype.reduce можна використовувати для ітерації масиву, додаючи поточне значення елемента до суми попередніх значень елементів.

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

Без значення за замовчуванням

Ви отримуєте TypeError

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

До функцій стрілок ES6

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

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

Нечислові входи

Якщо можливі введення нечислових номерів, ви можете вирішити це?

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

Нерекомендоване небезпечне використання eval

Ми можемо використовувати eval для виконання рядкового подання коду JavaScript. Використовуючи функцію Array.prototype.join для перетворення масиву в рядок, ми змінюємо [1,2,3] на "1 + 2 + 3", що оцінює на 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('+'))

Звичайно, показ сповіщення - це не найгірше, що може статися. Єдина причина, яку я включив у це, - це відповідь на питання Ортунда, оскільки я не думаю, що це було уточнено.


8
Ви знаєте, що ця магія reduce()все-таки на 25-30% повільніше, ніж простий індексований for()цикл після довгих років? jsperf.com/reduce-vs-loop/4
tevemadar

Це виникає в проблемах, якщо число до речі "0" - воно може трактуватися як рядок з будь-якої причини. Додавання 1 * a + 1 * b працювало для мене. Щодо швидкості, то це було легше писати, і мене не хвилює швидкість
Пітер Кей,

1179

У Ліспі це саме та робота reduce. Ви побачите такий код:

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

На щастя, у JavaScript ми також є reduce! На жаль, +це оператор, а не функція. Але ми можемо зробити це досить! Ось подивіться:

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

Хіба це не красиво? :-)

Навіть краще! Якщо ви використовуєте ECMAScript 2015 (він же ECMAScript 6 ), це може бути досить:

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

28
Припускаючи, що всі ми використовуємо ES2015, ми можемо зробити його менш багатослівним:[1, 2, 3].reduce((a,b)=>a+b)
Denys Séguret

1
Цікаво, чи порівняльний час виконання скорочення з функцією (a, b) порівнянний з ручною ітерацією та підсумовуванням чи є якась значна накладні витрати?
Триларіон

1
Я вважаю, що варто згадати, що відповідь насправді можна знайти на сторінці, на яку ви пов’язали: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Алекс Кон

2
Я додав би до 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
@Black зменшує масив в єдине значення.
Флоріан Маргаїн

204

Чому б не зменшити? Зазвичай це трохи інтуїтивно зрозуміло, але використовувати його для пошуку суми досить просто:

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

3
IE8 не підтримує його, і це не схоже, що jQuery має намір додавати його. Однак прототип має його.
Ізмаїл Смирнов

4
@Ishmael, ви можете використовувати UnderscoreJS, який повертається до реалізації веб-переглядача, якщо він доступний, або реалізує його самостійно.
Пабло Діаз

3
Про що контрінтуїтивно reduce()?
канон

3
@ s4nji Array.prototype.reduce() зменшує масив до єдиного повернутого значення.
канон

6
@ s4nji ... якщо ви не зменшуєте соус - у такому випадку ви збиваєте його до основних, тобто суми всіх ароматів без накладних витрат води. :-)
CB Du Rietz

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

3
Це набагато швидше, ніж рішення jQuery.each () вище.
Сердитий Ден

41
@Sprog: Однак використання (var i=0; i<arr.length; i++)ще швидше. І навіть тоді використання var sum=0; var i=arr.length; while(i--) sum += arr[i]ще швидше.
Рікінг

14
Використання for... inциклів на масивах працює в цьому випадку _ випадково_ і тому, що масиви розширюють об'єкти. Рішення Рікінга краще
Бенджамін Грюнбаум

2
@BenjaminGruenbaum за умови, що нічого не додало перелічених властивостей прототипу масиву ...
canon

1
@YSC ні, це не так. for...inЦикл в JavaScript має індекси, що є загальним каменем спотикання для кодерів , які очікують отримати значення. (Спробуйте for(var i in [1,2,3]) { console.log(i); }в консолі.)
Бурштин

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

87
Будь ласка, будь ласка, скористайтеся відповіддю reduceнижче; не оголошуйте змінні вари, коли у вас теж немає.
Бруно Грідер

9
Ця відповідь знаходиться під мета дискусією
Привид

11
Будь ласка, не використовуйте це, навіть якщо це "прийнята відповідь"; відповідь Флоріана нижче набагато краща!
Енді Сінклер

12
@BrunoGrieder "Не оголошуйте змінних варіантів, коли вам не потрібно" - це надзвичайно упереджена думка про імперативну мову , навряд чи кодовий запах будь-якої ділянки уяви. У відповіді Тайлера абсолютно нічого поганого, і єдина різниця між Тайлером і Флоріаном - це стиль.
Роб

5
Від ОП: Я думав, що $ .each може бути корисним, але я не знаю, як це здійснити. Це може бути не найкращим, але відповісти на запит ОП.


29

Це можливо, перебираючи всі елементи та додаючи їх на кожній ітерації до sumзмінної.

var array = [1, 2, 3];

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

JavaScript не знає масштабування блоку, тому sumбуде доступним:

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

Те саме, що було зазначено вище, однак коментується та готується як проста функція:

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
Хоча розумний, я знайшов би код, який оголошується sumза межами циклу, значно читабельнішим.
Бені Чернявський-Паскін

@ БеніЧернявський-Паскін Так, тут же ... Не знаю, чому я зробив це саме в той день ... Однак я дозволю, як є! Це лише приклад того, як ми могли б ... ;)
yckart

Оскільки ES6, javascript НЕ знає масштабування блоку за допомогою constта let. Таким чином, ви можете оголосити sumпоза forциклом як let sum = 0;. Ви також можете кешувати довжину масиву перед циклом якconst length = array.length;
KSK

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

Довідка: Array.prototype.reduce ()


6
Це не вдасться, якщо arrє [].

7
Додати значення за замовчуванням, наприклад , так:arr.reduce(function (a, b) { return a + b; }, 0);
МГЗ

15
// Given array 'arr'
var i = arr.length;
var sum = 0;
while (--i) sum += arr[i];

Це займе в середньому 1,57 мс / пробіг (вимірюється понад 1000 пробігів на масиві 100 випадкових нормальних чисел), порівняно з 3,604 мс / біг eval()методом вище та 2,151 мс / запуск зі стандартом для (i, довжина, ++ ) петля.

Методологічне зауваження: цей тест проводився на сервері сценаріїв Google Apps, тому їх двигуни javascript майже такі ж, як у Chrome.

EDIT: --iзамість i--економії 0,12 мс на кожному пробігу (i-- становить 1,7)

РЕДАКТ: Святий прихильник, не майте уваги на весь цей пост. Використовуйте вказаний вище метод redu (), це лише 1 мс / пробіг.


1
Я люблю таймінги, які ти використовував. Ваша відповідь не просто говорить "Виберіть мене, я найкращий!" Це замість цього показує нам, чому . У будь-якому випадку, це while (--i) do_somethingможе працювати і для інших речей.
Програми Redwolf

var sum = arr[0]
noobninja

12

Ви також можете використовувати ReduRight.

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

що дає результат 21.

Довідка: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/ReduceRight


Має бути швидше в хромі, оскільки оптимізація циклу JavaScript (тобто зменшення довжини) також може бути застосована до базової збірки, щоб зробити її швидшою.
Джек Гіффін

12

Хто шукає функціональний oneliner, як я? Прийняти це:

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

Ви можете додати початкове значення для зменшення як другий парам:arr.reduce(function(a, b) { return a + b;}, 0);
Нгз

Дякую! я включу це.
geek-merlin

12

Смішний підхід:

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

5
Скажіть, будь ласка, цю відповідь, пояснивши, що відбувається в цьому коді? Чому це працює? Що це робить саме? Ці речі допомагають покращити якість відповіді.
Ортунд

@ user40521 вже відповів на це так, як я думаю. Я цього не бачив.
електрон

Хоча це коротко і мило, і, безумовно, цікаво, воно також дуже неефективно. Використання reduce, безумовно, бажано для більшості, якщо не всіх випадків.
Ninjakannon

Errm,[1,"2;YourProgram.ripToShreds();3",4]
Програми

Тому я отримую, NaNколи намагаюся eval(['alert("removing your computer")',2,3].join("+"))відповісти неправильно
0/10

12

Гаразд, уявіть, що у вас є цей масив нижче:

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

Почнемо розглядати багато різних способів зробити це, оскільки я не зміг знайти тут всебічної відповіді:

1) Використання вбудованого скорочення ()

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

2) Використання для циклу

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

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

4) Використання масиву forEach

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

і називайте це так:

total(arr); //return 10

Не рекомендується прототипувати щось подібне до Array ...


10

Стандартне рішення 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 */

Це працює для мене (результат повинен бути 5). Я сподіваюся, що в такому рішенні немає прихованих недоліків.


1
Також будь-який програміст на C або Java міг би це зрозуміти.
Audrius Meskauskas

для простої мети підбиття всіх значень простий звичайний старий для циклу не має суперників за часом виконання
fedeghe

Проблема лише в тому, що це трохи дратує, коли у вас є 20 для циклів, які все вкладаються один в одного
Redwolf Programs

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

Таким чином ви можете помістити в масив усілякі екзотичні речі.

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

Я лише наполовину жартую.


26
Я наполовину
сміюсь

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

7

Я початківець з JavaScript і кодування взагалі, але я виявив, що простий і простий спосіб підсумовувати числа в масиві такий:

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

В основному, я хотів зробити свій внесок у це, тому що я не бачив багатьох рішень, які не використовують вбудовані функції, і цей метод легко написати та зрозуміти.


1
Чим це відрізняється від відповіді 2012 року чи цієї відповіді 2014 року ? Є два рішення, яких ви ще не бачили.
Дан Даскалеску

5

Короткий фрагмент коду JavaScript зробив би цю роботу:

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

Кілька людей запропонували додати .sum()метод до Array.prototype. Це, як правило, вважається поганою практикою, тому я не пропоную вам це робити.

Якщо ви все ще наполягаєте на тому, щоб це зробити, це короткий спосіб написати:

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

тоді: [1,2].sum(); // 3

Зауважте, що функція, додана до прототипу, використовує суміш функцій ES5 та ES6 та синтаксис стрілок. functionОголошується , щоб метод , щоб отримати thisконтекст від Arrayякий ви працюєте на. Я використовував =>для стислості всередині reduceдзвінка.


5

Використовуйте forцикл:

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

Або навіть forEachцикл:

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

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

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

Для простоти використовуйте 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

Не потрібно initial value! Оскільки, якщо не initial valueпередано жодний номер , значення callback functionне викликається у першому елементі списку, а перший елемент замість цього передається як initial value. Дуже c OO l особливість :)

[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

Ось елегантне однолінійне рішення, яке використовує алгоритм стека , хоча, можливо, знадобиться певний час, щоб зрозуміти красу цієї реалізації.

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

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

В основному, функція приймає масив і перевіряє, чи містить масив саме один елемент. Якщо помилково, він виводить останній елемент із стека та повертає оновлений масив.

Краса цього фрагмента полягає в тому, що функція включає arr[0]перевірку для запобігання нескінченного циклічного циклу. Після досягнення останнього пункту повертає всю суму.


4

Ви можете поєднати метод Redu () з лямбда-виразом:

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


3

Я бачив, що всі відповіді йдуть на "зменшити" рішення

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

3

Точність

Сортувати масив і почати суму найменших чисел (фрагмент показує різницю з несортовим)

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

Для багатовимірного масиву чисел використовують arr.flat(Infinity)


2

Прикольні трюки тут, у мене є вибір нитки з безліччю безпечних традиційних відповідей, не кешуючи довжину масиву.

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

Не кешуючи довжину масиву, компілятору JS необхідно пройти масив з кожною ітерацією циклу, щоб обчислити довжину, в більшості випадків це зайве накладні витрати. V8 та багато сучасних браузерів оптимізують це для нас, тому це менше турбот, ніж це було, але є більш старі пристрої, які отримують користь від цього простого кешування.

Якщо довжина може змінюватися, кешування може спричинити деякі несподівані побічні ефекти, якщо ви не знаєте, чому ви кешуєте довжину, але для функції багаторазового використання, яка є єдиною метою - взяти масив і разом додати значення, це чудово підходить.

Ось посилання CodePen для цієї функції arraySum. http://codepen.io/brandonbrule/pen/ZGEJyV

Можливо, це застарілий менталітет, який застряг у мене, але я не вважаю недоліком використовувати його в цьому контексті.


Питання кешування довжини - це червона оселедець. Двигуни JS оптимізують це для вас, не моргаючи.

2

Це справді чудові відповіді, але на всякий випадок, якщо числа є в такій послідовності, як у запитанні (1,2,3,4), ви можете легко зробити це, застосувавши формулу (n * (n + 1)) / 2 де n - останнє число


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

Цей код видаляє вашу операційну систему? Або він надсилає мені вашу особисту інформацію?

2

Це набагато простіше

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

Простий приклад методу:

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]));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.