Free JavaScript course. Sign Up for tracking progress →

JavaScript: Data aggregation (numbers)

One particular class of tasks that cannot be done without loops is data aggregation. These problems include searching for the maximum and minimum values, as well as finding sums and averages. Their main feature is that their result depends on the whole data set. Calculating the sum requires you to add all the numbers together, and calculating the maximum requires you to compare all the numbers.

Anyone who deals with numbers, e.g., accountants or marketers, will be familiar with these tasks. It's usually done using spreadsheet software like Microsoft Excel or Google Tables.

Let's consider a simple example: the sum of a set of numbers. We can implement a function to add numbers in a given range, including bounds. Here we have a range of numbers from a minimum value (lower bound) to a maximum (upper bound). For example, the range [1, 10] includes all integers from 1 to 10.

sumNumbersFromRange(5, 7); // 5 + 6 + 7 = 18
sumNumbersFromRange(1, 2); // 1 + 2 = 3

// The range [1, 1] is also a range
// it includes just one number, the bound of the range itself
sumNumbersFromRange(1, 1); // 1
sumNumbersFromRange(100, 100); // 100

To implement this function, we need a loop because adding numbers is an iterative process (an iteration for each number), and the number of iterations depends on the size of the range. Before looking at the code, try answering the questions below:

  • Which value should you initialize the counter with?
  • How will it change?
  • When should the loop stop?

Try and think through these questions first and then have a look at the code below:

const sumNumbersFromRange = (start, finish) => {
  // You can, of course, change the 'start' value
  // But the input arguments must be left unchanged
  // It makes the code easier to analyze
  let i = start;
  let sum = 0; // Sum initialization

  while (i <= finish) { // Move to the end of the range
    sum = sum + i; // Calculate sum for each number
    i = i + 1; // Go to the next number in the range
  }

  // Return loop result
  return sum;
};

The general structure of the loop here is standard. A counter initialized with a start value for the range, a loop with a condition to stop at the end of the range and, finally, a counter change at the end of the loop. The number of iterations in this type of loop is finish - start + 1. Thus, for the range from 5 to 7, it is 7 - 5 + 1, or three iterations.

The main difference from regular processing is related to the logic of computing the result. In aggregation tasks, there is always a variable that stores the result of the loop. In the code above, it is sum. With each loop iteration, this variable changes, adding another number from the range: sum = sum + i. The whole process looks like this:

// Calling sumNumbersFromRange(2, 5);
let sum = 0;
sum = sum + 2; // 2
sum = sum + 3; // 5
sum = sum + 4; // 9
sum = sum + 5; // 14
// 14 – the result of adding the numbers in the range [2, 5]

The sum variable has an initial value of 0. Why do you need to set the value at all? Any iterative operation starts with a value. You can't just declare an empty variable and start working with it within a loop. It will lead to an incorrect result:

// when there is no initial value
// js sets it to undefined
let sum;

// first iteration
sum = sum + 2; // ?

It will result in NaN, i.e. not a number, in sum. It occurs due to an attempt to add 2 and undefined. So you need to have an initial value. Why is 0 chosen in the code above? Well, it is easy to check that all the other options would lead to the wrong result. If the initial value is 1, the sum will be 1 more than it should be.

In mathematics, there is a concept of an identity element/neutral element, an element for each type of operation. Its meaning is easy to grasp. An operation with this element doesn't change the operand. For addition, any number plus zero results in the number itself. The same goes for subtraction. Even concatenation has a neutral element, which is an empty string: '' + 'one' will be 'one'.

Self-testing question. What is the neutral element of a multiplication operation?

Instructions

Write a function, multiplyNumbersFromRange(), that multiplies numbers in a given range, including its bounds. An example:

multiplyNumbersFromRange(1, 5); // 1 * 2 * 3 * 4 * 5 = 120
multiplyNumbersFromRange(2, 3); // 2 * 3 = 6
multiplyNumbersFromRange(6, 6); // 6
The exercise doesn't pass checking. What to do? 😶

If you've reached a deadlock it's time to ask your question in the «Discussions». How ask a question correctly:

  • Be sure to attach the test output, without it it's almost impossible to figure out what went wrong, even if you show your code. It's complicated for developers to execute code in their heads, but having a mistake before their eyes most probably will be helpful.
In my environment the code works, but not here 🤨

Tests are designed so that they test the solution in different ways and against different data. Often the solution works with one kind of input data but doesn't work with others. Check the «Tests» tab to figure this out, you can find hints at the error output.

My code is different from the teacher's one 🤔

It's fine. 🙆 One task in programming can be solved in many different ways. If your code passed all tests, it complies with the task conditions.

In some rare cases, the solution may be adjusted to the tests, but this can be seen immediately.

I've read the lessons but nothing is clear 🙄

It's hard to make educational materials that will suit everyone. We do our best but there is always something to improve. If you see a material that is not clear to you, describe the problem in “Discussions”. It will be great if you'll write unclear points in the question form. Usually, we need a few days for corrections.

By the way, you can participate in courses improvement. There is a link below to the lessons course code which you can edit right in your browser.

If you got stuck and don't know what to do, you can ask a question in our huge and friendly community