Arrays
Problem
Thirty grades
A teacher writes a program for the test scores. For five students they make five variables:
const score1 = 62;const score2 = 85;const score3 = 47;const score4 = 91;const score5 = 78;const sum = score1 + score2 + score3 + score4 + score5;console.log(sum);363But the class has thirty students. Thirty variables, thirty terms to add. And the highest score needs twenty-nine more comparisons. The loop from the last lesson does not help: it cannot go through score1, score2, score3, because those are separate names. We need many values under one name.
The idea
An array: a row of boxes
An array is a row of values under one name. Each value, an element of the array, has a number: its index. Indexes start at 0.
const scores = [62, 85, 47, 91, 78];console.log(scores[0]);console.log(scores[4]);console.log(scores.length);scores[2] = 50;console.log(scores[2]);6278550- The values go in square brackets
[ ], separated by commas. You don't write a type. You can mix numbers and text in one array, but usually all the elements are of one kind.
scores[0]is the first element,scores[4]the fifth. The last index is always 1 less than the count.scores.lengthis the number of elements. Here it is 5.scores[2] = 50;changes one element. The others stay the same.
If you don't know the values yet, but you know how many there are, you create an array with a size and fill it with zeros:
const booked = new Array(3).fill(0);booked[1] = 2;console.log(booked);[ 0, 2, 0 ]Unlike arrays in Java and C#, an array grows. push adds an element at the end:
const scores = [62, 85];scores.push(47);console.log(scores);console.log(scores.length);[ 62, 85, 47 ]3console.log of a whole array shows its elements in [ ]. That is handy for checking, but for the program's output you usually print the elements yourself.
More precisely, if you are curious
new Array(3)without.fill(0)does not hold zeros, but three empty slots. If you read one of them, you getundefined, "no value":
const booked = new Array(3);console.log(booked);console.log(booked[0]);[ <3 empty items> ]undefinedconstbefore the array means the name always points to the same array. Its elements can still be changed and added.
Try it
Which is which?
What will the program print?
const prices = [12, 7, 30, 5];console.log(prices[1] + prices[3]);We count from 0: prices[1] is 7 (the second), prices[3] is 5 (the fourth). 7 + 5 = 12. If you count from 1, you will take 12 and 30.
The idea
A loop through the array
Now the loop does help. The counter i becomes the index: it goes from 0 to the last one and on every round takes scores[i].
const scores = [62, 85, 47, 91, 78];let sum = 0;for (let i = 0; i < scores.length; i++) { sum += scores[i];}console.log(`Sum: ${sum}`);console.log(`Average: ${sum / scores.length}`);Sum: 363Average: 72.6The condition is i < scores.length, not a number. If you add all thirty grades in [ ], the loop does not change. This is called traversing the array.
In JavaScript / divides exactly, so the average comes out as 72.6 with nothing extra.
See it
The highest score
How do you find the biggest number? You remember the biggest one so far and replace it as soon as you see a bigger one.
const scores = [62, 85, 47, 91, 78];let max = scores[0];for (let i = 1; i < scores.length; i++) { if (scores[i] > max) { max = scores[i]; }}console.log(max); // 91Step by step, in words
- Five scores, side by side. The numbers below are the indexes: from 0 to 4.
- max starts from the first one: scores[0] is 62.
- i = 1: 85 > 62, so max becomes 85.
- i = 2: 47 is not bigger than 85. Nothing changes.
- i = 3: 91 > 85, so max becomes 91.
- i = 4: 78 < 91. Then i becomes 5, 5 < scores.length is false, and the loop stops.
- The highest score is 91.
max starts from the first element, not from 0. If all the scores were negative, 0 would "win" without being in the array. That is also why the loop starts from i = 1: the first one is already in max.
Try it
Find the bug
The program should print the sum 363. Instead it prints NaN.
Which line has the bug?
Pick the line with the bug.
<= the loop does one more round, with i = 5. The indexes of an array with 5 elements go from 0 to 4, and there is no element scores[5]. This is called going outside the array. In Java and C# the program stops with an error. In JavaScript it does not stop: scores[5] is undefined ("no value"), and 363 + undefined is NaN (Not a Number). The program keeps going with a wrong result, so watch the output. The fix is i < scores.length.The idea
for … of: for every element
When you need only the values and not the indexes, there is a shorter loop. How many students passed the exam (60 points or more)?
const scores = [62, 85, 47, 91, 78];let passed = 0;for (const score of scores) { if (score >= 60) { passed++; }}console.log(`Passed the exam: ${passed}`);Passed the exam: 4It reads "for each score of scores". In Java the same thing is called for-each. There is no counter and no index, so you cannot go outside the array. It is const because score does not change within one round: the next round gets a new score.
There is a limit too: you don't know which index you are at, and you cannot change the element.
More precisely, if you are curious
- If you write
score = 0;in the body, the program stops withTypeError, becausescoreisconst. Withlet scoreit would change only the variable, and the array would stay the same.
const scores = [62, 85, 47];try { for (const score of scores) { score = 0; }} catch (error) { console.log(`${error.name}: ${error.message}`);}TypeError: Assignment to constant variable.- There is also
for … in, withininstead ofof. It does not give you the elements but the indexes, and as text at that. For arrays, writefor … of:
const scores = [62, 85, 47];for (const i in scores) { console.log(i, typeof i);}0 string1 string2 string- To change elements, or when you need the index (for example for the neighbor
scores[i + 1]), use a regularfor.
Try it
Two names, one array
What will the program print?
const prices = [10, 20, 30];const sale = prices;sale[0] = 5;console.log(prices[0]);let b = a; and then b = 5; does not change a. With arrays, sale = prices does not make a new array, it gives a second name to the same one. That is why a change through sale also shows through prices. Why this is so, you will learn in the module "Classes and objects": an array is an object, and the variable points to it.More precisely, if you are curious
You make a real copy with a new array and a loop:
const prices = [10, 20, 30];const sale = [];for (const price of prices) { sale.push(price);}sale[0] = 5;console.log(prices[0], sale[0]);10 5[...prices] does the same:
const prices = [10, 20, 30];const sale = [...prices];sale[0] = 5;console.log(prices[0], sale[0]);10 5Try it
Put the lines in order
The program should find the lowest price. Put its lines in order.
min = prices[i];let min = prices[0];if (prices[i] < min) {const prices = [18, 7, 25, 12];for (let i = 1; i < prices.length; i++) {}}console.log(min);
Exercise
Working with an array
Solve the exercises in your editor. Each program first reads how many numbers there are, then the numbers themselves, one per line:
const n = Number(await ask(""));const numbers = [];for (let i = 0; i < n; i++) { numbers.push(Number(await ask("")));}At the top are the lines for ask(), and at the end rl.close(), as in the lesson "Input and output".
1. Sum, even, odd. Print the sum of all the numbers, of the even ones and of the odd ones.
3123Sum: 6Even: 2Odd: 42. Reversed. Create a new array with the same numbers in reverse order and print it on one line.
5123455 4 3 2 13. Lowest, highest, average. In one pass through the array.
549274Lowest: 2Highest: 9Average: 5.2Exercise
Sorting and counting
4. Sorting. Sort the numbers from the smallest to the biggest. Hint: go through the array, and if two neighbors are in the wrong order, swap them (swapping is from the lesson on variables). Repeat until there is nothing left to swap. This is called bubble sort: the big numbers "bubble up" to the end.
5427193253 7 19 25 425. Longest run. Find the longest run of equal numbers one after another.
822555155The number 5, 3 times in a row6. Grade statistics. Read grades from 2 to 6 and print how many there are of each kind. Hint: an array counts with 7 elements, where the grade is the index: counts[grade]++.
864563265Excellent (6): 3Very good (5): 2Good (4): 1Fair (3): 1Poor (2): 1More exercises
- Median. The number in the middle of the sorted array. For 3, 1, 4, 1, 5 the median is 3. If there is an even count of numbers, the median is the average of the two in the middle: for 7, 1, 3, 9 it is (3 + 7) / 2 = 5.
- Symmetric array. Does it read the same from front to back and from back to front? 1 2 3 2 1 is symmetric, 1 2 3 1 is not.
- Roman numerals. Read a number from 1 to 3999 and print it in Roman numerals: 2024 is MMXXIV, 1994 is MCMXCIV. Hint: two arrays side by side, with the values
1000, 900, 500, 400, 100, …, 1and with the symbols"M", "CM", "D", "CD", "C", …, "I". While the number is at least the current value, add the symbol and subtract the value.
Test