Is there a more universal solution for finding the sum of squares of all elements in an array?

var out = 0; function squareSum(numbers){ for (var i = 0; i < numbers.length; i++) { var res = numbers[i] * numbers[i]; out += res; console.log(out); } } squareSum([1, 2, 2]); 

  • where much more versatile? - Grundy
  • @Grundy really), criticize my code and compare it with other implementations - spectre_it

5 answers 5

Since the question (actually) comes down to code inspection, I consider it necessary to comment on each line of the source code:

 // Здесь вы определяете ГЛОБАЛЬНУЮ переменную, засоряя при этом глобальное пространство имен. // В будущем это может привести к очень неочевидным проблемам при отладке. var out = 0; function squareSum(numbers){ // Стоит отметить, что условие перехода к следующей итерации // цикла выполняется для КАЖДОГО его элемента. Это значит, // что имея массив из 10 тысяч элементов вы 10 тысяч раз выполните // numbers.length. Согласитесь, это не очень то эффективно (особенно // если учесть, что длина массива не меняется). for (var i = 0; i < numbers.length; i++) { // Переменная res - не нужна. Кроме того, получение элемента массива // занимает некоторое время, поэтому на больших массивах выполнять // эту операцию дважды - не лучшая идея. var res = numbers[i] * numbers[i]; // Используя переменную из глобального контекста вы сломаете // любой другой код, который от нее зависит. Да, сейчас вы об // этом помните, но где гарантии, что вы (или ваш последователь) // не станет использовать эту же переменную где-то еще? out += res; // Эта конструкция тоже разрушает "чистоту" функции. // Представьте, что вам нужно будет выкинуть все console.log // из кода. Что будете делать? console.log(out); } } // Ок, но функция, результат которой не используется - не нужна. squareSum([1, 2, 2]); 

Well, now an example of how absolutely the same (including the output of intermediate values ​​in the console) can be done better.

(I will not consider the option of changing the approach to the functional one, since this has already been done in the adjacent answers.)

 function squareSum(numbers, logger) { var res = 0, // Если последний аргумент опущен, то заменяем реальную // функцию-логгер на заглушку, которая не будет делать ничего. log = (typeof logger === 'function') ? logger : function() {}; for (var i = 0, len = numbers.length; i < len; i++) { res += Math.pow(numbers[i], 2); log(res); } return res; } var sum = squareSum([1, 2, 2], console.log); 
  • one
    I beg your petition, but do not modern browsers optimize such things? does the programmer still need to keep track of this? It should be noted that the condition for the transition to the next iteration // of the cycle is fulfilled for EACH element. This means that if you have an array of 10 thousand elements, you will execute // numbers.length 10 thousand times. Agree, this is not very effective (especially // if you consider that the length of the array does not change). - spectre_it
  • one
    @ stas0k, In general, instead of i < arr.length can be any calculated expression. And this means that it will actually be calculated every time. Well, each calculation of the length (given that the arrays in js do not have fixed sizes) requires extra body movements from the engine. Such things are better taken into account. In general, since the question about the code review, I tried to indicate as much as possible potentially problematic / not good things. - Dmitriy Simushev
  • thank you, the advice is really valuable, that's why I marked your answer to the question as an answer). Ilya Kantor, in a conversation, somehow mentioned that now the engines have learned how to do such optimizations and do not calculate the array length in a cycle a thousand times, so I did not attach any importance to this. Thanks you! - spectre_it
  • logger pass in the parameter, this is nonsense. numbers.length - will not be calculated each time, JS is not so dumb. And the person about the algorithm asked mine, and not about formatting the code. - Goncharov Alexander
  • one
    numbers.length , but as far as numbers.length you don’t see the point. Look at my comment above " In a general view, instead of i < arr.length can be any calculated expression ". In other words, there can be any laborious expression that depends only on the source array. If there is a chance to save on the calculation of a constant expression - it should be used. This is from best practice. Yes, for the length of the array, some JS engines can perform certain optimizations, but in the case of an arbitrary expression, this is not so. - Dmitriy Simushev

You can count through the map and reduce:

 function squareSum(numbers){ return numbers.map(function (n) { return n * n; }) .reduce(function (sum, n) { return sum + n; }); } alert(squareSum([1, 2, 2])); 

View code on jsfiddle

But in general - what prevented you from google this common task? For example, there are already 4 solutions .

  • in Google, I cannot get feedback, which is not correct in my code and of course I hope to get advice from more experienced comrades, tricks, different programming techniques - spectre_it September

 function squareSum(numbers){ var result = 0; numbers.forEach(function(item) { result += Math.pow(item, 2); }); return result; } console.log( squareSum([1, 2, 2]) ); 

In this example, we go through the array using the forEach() method, each element of the item array is squared using the Math.pow(число, степень) method Math.pow(число, степень) .

The forEach() method performs the specified function once for each element in the array.

MDN Array.prototype.forEach ()

The Math.pow () method returns a base raised to a power index.

MDN Math.pow ()

  • one
    Then you should use reduce instead of forEach - Pavel Mayorov

Using the Math.hypot method, which returns the square root of the sum of the squares of its arguments. By squaring the result, we get the desired amount.

 function squareSum() { return Math.pow(Math.hypot.apply(null, arguments[0]), 2); } console.log(squareSum([1, 2, 2])); 

  • I think it is worth pointing out that the function Math.hypot is far from everywhere - Dmitriy Simushev
  • Why do you use arguments[0] instead of a normal argument? They took the optimization off from scratch ... - Pavel Mayorov

 function squareSum(numbers){ return numbers.reduce(function(sum, n){ return (n*n) + sum; }, 0) } console.log(squareSum([1,2,2]));