30 Days Of JavaScript.9E
Day 9. Higher Order Function_Exercise
👟Level 1.
const countries = ['Finland', 'Sweden', 'Denmark', 'Norway', 'IceLand']
const names = ['Asabeneh', 'Mathias', 'Elias', 'Brook']
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const products = [
{ product: 'banana', price: 3 },
{ product: 'mango', price: 6 },
{ product: 'potato', price: ' ' },
{ product: 'avocado', price: 8 },
{ product: 'coffee', price: 10 },
{ product: 'tea', price: '' },
]
1) Explain the difference between forEach, map, filter, and reduce.
-
forEach()
executes the given function, iterating through the elements of an array. -
map()
iterates and modifies an array, implementing the given function. -
filter()
filters the elements of an array by the given condition at the parameter. -
reduce()
executes certain function, running through element by element in an array and returning a single value.
Define a callback function before you use it in forEach, map, filter or reduce.
3) Use forEach to console.log each country in the countries array.
//function declaration
countries.forEach(function(country) {
console.log(country);
})
//arrow function implicit return
countries.forEach((country) => console.log(country));
4) Use forEach to console.log each name in the names array.
names.forEach((name) => console.log(name));
5) Use forEach
to console.log each number in the numbers array.
numbers.forEach((num) => console.log(num));
6) Use map to create a new array by changing each country to uppercase in the countries array.
//defining callback function
function upperCase(str) {
return str.toUpperCase();
}
const upperCaseCountries = countries.map((country) =>
upperCase(country)
);
console.log(upperCaseCountries);
// (5) ['FINLAND', 'SWEDEN', 'DENMARK', 'NORWAY', 'ICELAND']
//using arrow function
const upperCaseCountries = countries.map((country) =>
country.toUpperCase()
);
console.log(upperCaseCountries);
7) Use map to create an array of countries length from countries array.
function getLength(str) {
return str.length;
}
const lengthOfCountries = countries.map((country) =>
getLength(country)
);
console.log(lengthOfCountries); // (5) [7, 6, 7, 6, 7]
8) Use map to create a new array by changing each number to square in the numbers array.
function square(num) {
return num * num;
}
const squareNum = numbers.map((num) => {
return square(num);
});
console.log(squareNum);
// (10) [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
9) Use map to change to each name to uppercase in the names array.
function upperCase(str) {
return str.toUpperCase();
}
const upperCaseName = names.map((name) => {
return upperCase(name)
});
console.log(upperCaseName);
// (4) ['ASABENEH', 'MATHIAS', 'ELIAS', 'BROOK']
I omitted the return
keyword at line 2, and the resulting elements of the array were all ‘undefined’.
Be sure to write
return
when using function declaration! When using arrow function, I can skipreturn
keyword(implicit return).
10) Use map to map the products array to its corresponding prices.
- First approach (X)
function getPrice(name) {
for (let i = 0; i < products.length; i++) {
if (products[i].product === name) {
return products[i].price;
}
}
}
const prices = products.map((name) => getPrice(name));
console.log(prices);
- Problem 01. Setting a function
I struggled, trying to use forEach
for the getPrice
function. So at my first answer above, I just used for loop
. But I now know that using for
all the time wouldn’t be efficient. At first, I tried to add a condition inside the forEach
method like below.
function getPrice(name) {
products.forEach((element) => {
if (element.product === name) {
return element.price;
}
})
}
getPrice('banana'); // undefined
It didn’t work, so I searched stackflow and found a comment that I shouldn’t use return
in forEach()
. forEach
doesn’t return anything. I thought return
would work because it was anyway inside the function. Well, it didn’t work so I changed return
to console.log
and the function worked.
function getPrice(name) {
products.forEach((element) => {
if (element.product === name) {
return element.price;
}
})
}
getPrice('banana'); // 3
—
- Problem 02. Setting parameters in
map()
At my initial approach, after I compromised to use for loop
, I was having trouble with printing out the array at this part.
const prices = products.map((name) => getPrice(name));
console.log(prices);
It would just return an array filled with ‘undefined’. I first thought it was the problem of the function, but it was not. I had to think through what the function is doing with the parameter. The parameter I’m going to pass is each element of the products
array, which is an object. The function getPrice
is designed to take a product name as a parameter and return the price of that product.
So if I just pass name
to the function getPrice
, an object containing two key-value pairs will be passed as a parameter. To modify the object into the value of that object, I used dot notation like below.
const prices = products.map((element) =>
getPrice(element.product)
);
console.log(prices);
- Second approach: using for loop (O)
function getPrice(name) {
for (let i = 0; i < products.length; i++) {
if (products[i].product === name) {
return products[i].price;
}
}
}
const prices = products.map((element) =>
getPrice(element.product)
);
console.log(prices);
// (6) [3, 6, ' ', 8, 10, '']
- Third approach: using
forEach()
(X)
function getPrice(name) {
let price;
products.forEach((element) => {
if (element.product === name) {
let price = element.price;
}
})
return price;
}
const prices = products.map((element) =>
getPrice(element.product)
);
console.log(prices);
Writing the last code, I encountered another problem. The function using forEach()
couldn’t use return inside forEach()
, so I had to think of another way.
I first put let price = element.price
inside if
, but got an error that ‘price’ wasn’t defined. So, I defined ‘price’ before forEach()
and tried to return the value after forEach()
ends. It didn’t work.
The problem was that, I should have wrote price = element.price
rather than let price = element.price
. let
would just assign a new variable. To change the value, I had to use only the assigning operatior(=) without let
.
- Final approach: using
forEach()
(O)
function getPrice(name) {
let price;
products.forEach((element) => {
if (element.product === name) {
price = element.price;
}
})
return price;
}
const prices = products.map((element) =>
getPrice(element.product)
);
console.log(prices);
// (6) [3, 6, ' ', 8, 10, '']
11) Use filter to filter out countries containing ‘land’.
const landCountries = countries.filter((element) =>
element.includes('land')
);
console.log(landCountries);
// ['Finland']
12) Use filter to filter out countries having six character.
const sixCharacter = countries.filter((element) =>
element.length === 6
);
console.log(sixCharacter);
//(2) ['Sweden', 'Norway']
13) Use filter to filter out countries containing six letters and more in the country array.
const sixOrMoreCharacter = countries.filter((element) =>
element.length >= 6
);
console.log(sixOrMoreCharacter);
//(5) ['Finland', 'Sweden', 'Denmark', 'Norway', 'IceLand']
14) Use filter to filter out country starting with ‘E’.
const startsWithE = countries.filter((element) =>
element.startsWith('E')
);
console.log(startsWithE);
// []
15) Use filter to filter out only prices with values.
const priceValues = products.filter((element) =>
typeof element.price === `number`
);
console.log(priceValues);
// [{product: 'banana', price: 3}, {product: 'mango', price: 6}, {product: 'avocado', price: 8}, {product: 'coffee', price: 10}]
16) Declare a function called getStringLists which takes an array as a parameter and then returns an array only with string items.
function getStringLists(arr) {
const stringItems = arr.filter((element) =>
typeof element === 'string')
return stringItems;
}
const mixedArray = [1, '650', 'lamp', true, 90];
console.log(getStringLists(mixedArray));
// (2) ['650', 'lamp']
17) Use reduce to sum all the numbers in the numbers array.
const sum = numbers.reduce((prev, cur) =>
prev + cur, 0
);
console.log(sum); // 55
18) Use reduce to concatenate all the countries and to produce this sentence: Estonia, Finland, Sweden, Denmark, Norway, and IceLand are north European countries.
const countriesWithoutLastCountry = countries.slice(0, countries.length - 1);
const lastCountry = countries[countries.length - 1];
const sentence = countriesWithoutLastCountry.reduce((prev, cur) =>
prev + ', ' + cur
);
console.log(`${sentence} and ${lastCountry} are north European countries.`);
// Finland, Sweden, Denmark, Norway and IceLand are north European countries.
In this code, I separated the last country from the others, to add a string ‘and’ between them. Then, I used reduce()
to run through the elements of countriesWithoutLastCountry
array, to add a comma between each element. I thought the job was similar to join()
array method.
19) Explain the difference between some and every.
-
some()
checks if the array has at least one element that satisfies the given condition. -
every()
checks if all the elements of the array satisfy the condition.
20) Use some to check if some names’ length is greater than seven in names array.
const longerThanSeven = names.some((element) =>
element.length > 7
);
console.log(longerThanSeven);
// true
21) Use every to check if all the countries contain the word land.
const allLandCountries = countries.every((element) =>
element.includes('land')
);
console.log(allLandCountries);
// false
21) Explain the difference between find and findIndex.
find()
returns the first value of the element satisfying the given condition, while findIndex()
returns the first index of the element satisfying the condition.
22) Use find to find the first country containing only six letters in the countries array.
const firstSixLetterCountry = countries.find((element) =>
element.length === 6
);
console.log(firstSixLetterCountry); // Sweden
23) Use findIndex to find the position of the first country containing only six letters in the countries array.
const firstSixLetterCountry = countries.findIndex((element) =>
element.length === 6
);
console.log(firstSixLetterCountry); // 1
24) Use findIndex to find the position of Norway. If it doesn’t exist in the array you will get -1.
const norwayIndex = countries.findIndex((element) =>
element == 'Norway'
);
console.log(norwayIndex); // 3
25) Use findIndex to find the position of Russia. If it doesn’t exist in the array you will get -1.
const russiaIndex = countries.findIndex((element) =>
element == 'Russia'
);
console.log(russiaIndex); // -1
👟Level 2.
1) Find the total price of products by chaining two or more array iterators(eg. arr.map(callback).filter(callback).reduce(callback)).
First, I executed all the steps separately to test if the code works.
//setting a function that gets the price value from each element
function getPrice(name) {
let price;
products.forEach((element) => {
if (element.product === name) {
price = element.price;
}
})
return price;
}
//the array of all prices, using map
const priceArray = products.map((element) =>
getPrice(element.product)
);
//the array of prices that have values, using filter
const priceValueArray = priceArray.filter((element) =>
typeof element == 'number'
);
//the sum of prices, using reduce
const sumOfPrices = priceValueArray.reduce((prev, cur) =>
prev + cur, 0
);
Here’s the completed version, chaining three built-in methods: forEach()
, filter()
, and reduce()
.
function getPrice(name) {
let price;
products.forEach((element) => {
if (element.product === name) {
price = element.price;
}
})
return price;
}
const sumOfValues = products.map((element) =>
getPrice(element.product)).filter((element) =>
typeof element == 'number').reduce((prev, cur) =>
prev + cur, 0
);
console.log(sumOfValues); //27
2) Find the sum of price of products using only reduce, reduce(callback)).
- First Approach (X)
function getPrice(name) {
let price;
products.forEach((element) => {
if (element.product === name) {
price = element.price;
}
})
return price;
}
const sumOfPrices = products.reduce((prev, cur) => {
getPrice(prev.product) + getPrice(cur.product)
}, 0);
I thought that reduce()
is similar to forEach()
in that it also goes through all the elements in the array. At first, I brought the getPrice
function, and tried to add the price values in the reduce()
.
- Second Approach (X, not only using reduce)
function getPrice(name) {
let price;
products.forEach((element) => {
if (element.product === name) {
price = element.price;
}
})
return price;
}
const prices = products.map((element) =>
getPrice(element.product)
);
const sumOfPrices = prices.reduce((prev, cur) =>
//converting an empty string to a number(casting)
+prev + +cur, 0
);
console.log(sumOfPrices); // 27
- Third Approach (O)
function getPrice(element) {
return element.price;
}
const sumOfPrices = products.reduce((acc, cur) =>
+acc + +getPrice(cur), 0
);
console.log(sumOfPrices); // 27
Watching some tutorial videos about reduce()
, I could finally get how the method works, and how I should write the code. The getPrice
function gets an element as a parameter and return the value of the price property of the element. Then, the reducer goes through all the elements, adding the value returned by getPrice()
function one by one. I added plus sign before the values, so that the empty string value(‘’) converts into number. I can also use Number()
or parseInt()
.
array.reduce(() => {}, initialValue);
array.reduce(function() {}, initialValue);
3) Declare a function called categorizeCountries which returns an array of countries which have some common pattern(e.g. ‘land’, ‘ia’, ‘island’,’stan’) in the countries array.
- First Approach (a single job)
function categorizeCountries(arr) {
const landCountries = arr.filter((element) =>
element.includes('land'));
return landCountries;
}
console.log(categorizeCountries(countries));
// (11) ['Finland', 'Iceland', 'Ireland', 'Marshall Islands', 'Netherlands', 'New Zealand', 'Poland', 'Solomon Islands', 'Swaziland', 'Switzerland', 'Thailand']
- Second Approach (multiple jobs, but repetitive)
Then I tried making a new array of objects, containing the category and countries.
function categorizeCountries(arr) {
const categorized = [];
const land = {};
land.category = 'land';
land.countries = arr.filter((element) =>
element.includes('land'))
categorized.push(land);
const ia = {};
ia.category = 'ia';
ia.countries = arr.filter((element) =>
element.endsWith('ia'))
categorized.push(ia);
return categorized;
}
console.log(categorizeCountries(countries));
// [{category: 'land', countries: Array(11)}, {category: 'ia', countries: Array(35)}]
- Final Approach 1 (shortened, the array of objects)
I thought the process was unnecessarily repetitive, so I made a loop using built-in array methods. Using the code below, I can always add a new category in the pattern
array and add another object of that category.
function categorizeCountries(arr) {
const pattern = ['land', 'ia', 'Island', 'stan'];
const categorized = [];
pattern.forEach((element) => {
const sort = {};
//use string template
sort.category = `${element}`;
sort.countries = arr.filter((country) =>
country.includes(`${element}`))
categorized.push(sort)
});
return categorized;
}
console.log(categorizeCountries(countries));
// (4) [{category: 'land', countries: Array(11)}, {category: 'ia', countries: Array(39)}, {category: 'Island', countries: Array(2)}, {category: 'stan', countries: Array(7)}]
First, I made a mistake of just putting ‘element’ at line 6. To filter each countries, I had to check if certain country name has certain string. So, I used string template(${ }
) to convert a variable into a string.
- Final Approach 2 (the array of countries)
function categorizeCountries(arr) {
const pattern = ['land', 'ia', 'Island', 'stan'];
const categorized = [];
pattern.forEach((element) => {
const sort = [];
//use string template
let category = `${element}`;
categorized.push(arr.filter((country) =>
country.includes(`${element}`)))
});
return categorized;
}
console.log(categorizeCountries(countries));
// (4) [['Finland', 'Iceland',...], ['Albania', 'Algeria',...], ['Marshall Islands', 'Solomon Islands'], ['Afghanistan', 'Kazakhstan',...]]
4) Create a function which return an array of objects, which is the letter and the number of times the letter use to start with a name of a country.
function initialAndTimes(arr) {
const array = [];
const abc = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
abc.forEach((letter) => {
const object = {};
object.letter = `${letter}`;
object.times = arr.filter((country) =>
country.startsWith(`${letter}`)).length;
array.push(object);
})
return array;
}
console.log(initialAndTimes(countries));
// (26) [{letter: 'A', times: 11}, {letter: 'B', times: 17},... {letter: 'Z', times: 2}]
- Mistakes I’ve been through
1) I declared the object outside the forEach()
and the returned value was all ‘Z’. The objects are made inside forEach()
, so I have to declare it inside.
2) I set abc
as a string. I forgot that the built-in methods I’m using are only available with arrays. So, I changed the string to an array.
3) I didn’t put curly braces at line 4. If a callback function has more than one line, I have to put curly braces.
5) Declare a getFirstTenCountries function and return an array of ten countries. Use different functional programming to work on the countries.js array.
function getFirstTenCountries() {
const firstTenCountries = countries.filter((element) => {
return countries.indexOf(element) < 10;
})
return firstTenCountries;
}
/*
function getFirstTenCountries() {
const firstTenCountries = countries.filter((element) =>
countries.indexOf(element) < 10
)
return firstTenCountries;
}
*/
console.log(getFirstTenCountries());
// (10) ['Afghanistan', 'Albania', 'Algeria', 'Andorra', 'Angola', 'Antigua and Barbuda', 'Argentina', 'Armenia', 'Australia', 'Austria']
I had a problem with because it had an error when I omitted the curly braces. So I searched it on stackflow, and found the comment below.
The pair of braces forms a block, containing a list of statements. I need to use a return statement explicitly to make the function return something.
If I omit the braces, the arrow function has a concise body, which consists solely of a single expression whose result will implicitly become the return value of the function.
6) Declare a getLastTenCountries function which returns the last ten countries in the countries array.
function getLastTenCountries() {
const lastTenCountries = countries.filter((element) =>
countries.indexOf(element) > countries.length - 11
)
return lastTenCountries;
}
console.log(getLastTenCountries());
// (10) ['United States', 'Uruguay', 'Uzbekistan', 'Vanuatu', 'Vatican City', 'Venezuela', 'Vietnam', 'Yemen', 'Zambia', 'Zimbabwe']
I wonder if there’s another way of printing certain numbers of array, using functional programming. If you have any idea, leave a comment below!
7) Find out which letter is used many times as initial for a country name from the countries array(e.g. Finland, Fiji, France etc).
function mostUsedInitial(arr) {
const abc = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
const initial = [];
abc.forEach((letter) => {
let initialNum = arr.filter((country) =>
country.startsWith(`${letter}`)).length;
initial.push(initialNum);
})
let max = Math.max(...initial);
let index = initial.indexOf(max);
return abc[index];
}
console.log(mostUsedInitial(countries)); // S
The index of the character at abc
array, and the index of the number of times the character is used at initial
array are corresponding.
👟Level 3.
1) Use the countries information in the data folder. Sort countries by name, by capital, by population.
const sortedCountries = [];
const nameObject = {};
nameObject.name = countries_data.map((element) =>
element["name"]
);
sortedCountries.push(nameObject);
const capitalObject = {};
capitalObject.capital = countries_data.map((element) =>
element["capital"]
);
sortedCountries.push(capitalObject);
const populationObject = {};
populationObject.population = countries_data.map((element) =>
element["population"]
);
sortedCountries.push(populationObject);
console.log(sortedCountries);
// (3)[{name: Array(250)}, {capital: Array(250)}, {population: Array(250)}]
I made a new array containing three objects, each sorted by name, capital, and population. Again, the code was unnecessarily repetitive, so I shortened it by adding an array of criterias like below.
const sortedCountries = [];
const criteria = ["name", "capital", "population"];
criteria.forEach((element) => {
const object = {};
object[element] = countries_data.map((country) =>
country[element]);
sortedCountries.push(object);
})
console.log(sortedCountries);
// (3)[{name: Array(250)}, {capital: Array(250)}, {population: Array(250)}]
2) Find the 10 most spoken languages from countries_data.js file.
- Expected output
console.log(mostSpokenLanguages(countries, 10))
[
{country: 'English',count:91},
{country: 'French',count:45},
{country: 'Arabic',count:25},
{country: 'Spanish',count:24},
{country:'Russian',count:9},
{country:'Portuguese', count:9},
{country:'Dutch',count:8},
{country:'German',count:7},
{country:'Chinese',count:5},
{country:'Swahili',count:4}
]
console.log(mostSpokenLanguages(countries, 3))
[
{country: 'English',count: 91},
{country: 'French',count: 45},
{country: 'Arabic',count: 25},
]
From the expected output, I assume that I should first sort the languages by its number of use. Then, from the second parameter I’ll get the number of objects that will be logged on console. First, I made a small function that prints out the counts of each language.
- Step 1: Make a function that counts the language use
//print out only "languages" arrays from each objects
const allLangs = countries_data.map((element) =>
element.languages
);
function getEngSum() {
let sum = 0;
allLangs.forEach((element) => {
const langNum = element.filter((lang) =>
lang == 'English').length;
sum += langNum;
})
return sum;
}
console.log(getEngSum()); // 91
The function filters each element(which is an array) of allLangs
by checking if any element of the array contains a certain language(in this case ‘English’), and adds the length of passed arrays to sum
.
- Step 2: Expand the function
After I make an array of languages, I can pass each language to an argument and get the count.
//some notes for the code
function getLangNum(language) {
allLangs.forEach((element) => {
const langNum = element.filter((lang) =>
lang == language).length;
})
}
- Step 3: Make an array of languages
First, I made an array called mixedLangs
. It first converts all array values into a string, and split it in the place of comma, so that each language elements from each arrays becomes an element in a single array. Then, I used Set
to remove the overlapping languages. So what i made is sort of a language index.
const allLangs = countries_data.map((element) =>
element.languages
);
const mixedLangs = allLangs.toString().split(',');
// remove the overlapping element
const langIndex = [...new Set(mixedLangs)];
console.log(langIndex); // (123) ['Pashto', 'Uzbek',... "Northern Ndebele"]
- Step 4: Print out an array of objects, containing each language and its count
const allLangs = countries_data.map((element) =>
element.languages
);
const mixedLangs = allLangs.toString().split(',');
// remove the overlapping element
const langIndex = [...new Set(mixedLangs)];
function getLangSum(language) {
let sum = 0;
allLangs.forEach((element) => {
const langNum = element.filter((lang) =>
lang == language).length;
sum += langNum;
})
return sum;
}
const spokenLangs = [];
langIndex.forEach((element) => {
const object = {};
object.language = `${element}`;
object.count = getLangSum(`${element}`);
spokenLangs.push(object);
})
console.log(spokenLangs);
// (123) [{language: 'Pashto', count: 1}, {language: 'Uzbek', count: 2},... {language: 'Northern Ndebele', count: 1}]
- Step 5: Sort the array by the counts
Now that I have a list of objects, I should sort those objects by the number of count. So I had to sort the object elements by the values inside each objects. sort()
could also take a callback function(stackoverflow, document). The counts(numeric values) should be sorted in descending order, so I put a compare function.
A thing to notice is that what I pass as a, b to a function is the elements of spokenLangs
. So, to access to the count property, I passed something a.count and b.count. I cannot just put ‘a - b’ or ‘b - a’.
const mostSpokenLangs = spokenLangs.sort((a, b) =>
b.count - a.count
);
console.log(mostSpokenLangs);
/* (123) [{language: 'English', count: 91}, {language: 'French', count: 45},... {language: 'Northern Ndebele', count: 1}]
- Step 6(Final Answer): Make a function that prints out specified number of objects
This step is similar to 5) at Level 2, which is to use filter()
to print out certain number of elements.
function mostSpokenLanguages(number) {
//make a language index
const allLangs = countries_data.map((element) =>
element.languages
);
const mixedLangs = allLangs.toString().split(',');
const langIndex = [...new Set(mixedLangs)]
//get the count of each language
function getLangSum(language) {
let sum = 0;
allLangs.forEach((element) => {
const langNum = element.filter((lang) =>
lang == language).length;
sum += langNum;
})
return sum;
}
//make objects containing language and count
const spokenLangs = [];
langIndex.forEach((element) => {
const object = {};
object.language = `${element}`;
object.count = getLangSum(`${element}`);
spokenLangs.push(object);
})
//sort the objects by the counts in descending order
const mostSpokenLangs = spokenLangs.sort((a, b) =>
b.count - a.count
);
//print out the specified number of objects
const printOut = mostSpokenLangs.filter((element) =>
mostSpokenLangs.indexOf(element) < number)
return printOut;
}
console.log(mostSpokenLanguages(3));
//(3) [{language: 'English', count: 91}, {language: 'French', count: 45}, {language: 'Arabic', count: 25}]
3) Use countries_data.js file create a function which create the ten most populated countries.
- Expected Output
console.log(mostPopulatedCountries(countries, 10))
[{country: 'China', population: 1377422166},
{country: 'India', population: 1295210000},
{country: 'United States of America', population: 323947000},
{country: 'Indonesia', population: 258705000},
{country: 'Brazil', population: 206135893},
{country: 'Pakistan', population: 194125062},
{country: 'Nigeria', population: 186988000},
{country: 'Bangladesh', population: 161006790},
{country: 'Russian Federation', population: 146599183},
{country: 'Japan', population: 126960000}]
console.log(mostPopulatedCountries(countries, 3))
[{country: 'China', population: 1377422166},
{country: 'India', population: 1295210000},
{country: 'United States of America', population: 323947000}]
For this one, I should only sort the objects by its population. Though the populations are numeric values, I should put compare functions in sort()
.
function mostPopulatedCountries(number) {
//make a new array containing objects with country and population
const countriesAndPopulation = [];
countries_data.forEach((element) => {
const object = {};
object.country = element.name;
object.population = element.population;
countriesAndPopulation.push(object);
})
//sort the objects by its population
const mostPopulated = countriesAndPopulation.sort((a, b) =>
b.population - a.population
);
//print out the specified number of objects
const printOut = mostPopulated.filter((element) =>
mostPopulated.indexOf(element) < number)
return printOut;
}
console.log(mostPopulatedCountries(3));
// (3) [{country: 'China', population: 1377422166}, {country: 'India', population: 1295210000}, {country: 'United States of America', population: 323947000}]
4) Try to develop a program which calculate measure of central tendency of a sample(mean, median, mode) and measure of variability(range, variance, standard deviation).
In addition to those measures find the min, max, count, percentile, and frequency distribution of the sample. You can create an object called statistics and create all the functions which do statistical calculations as method for the statistics object. Check the output below.
- Expected output
const ages = [31, 26, 34, 37, 27, 26, 32, 32, 26, 27, 27, 24, 32, 33, 27, 25, 26, 38, 37, 31, 34, 24, 33, 29, 26]
console.log('Count:', statistics.count()) // 25
console.log('Sum: ', statistics.sum()) // 744
console.log('Min: ', statistics.min()) // 24
console.log('Max: ', statistics.max()) // 38
console.log('Range: ', statistics.range() // 14
console.log('Mean: ', statistics.mean()) // 30
console.log('Median: ',statistics.median()) // 29
console.log('Mode: ', statistics.mode()) // {'mode': 26, 'count': 5}
console.log('Variance: ',statistics.var()) // 17.5
console.log('Standard Deviation: ', statistics.std()) // 4.2
console.log('Frequency Distribution: ',statistics.freqDist())
// [(20.0, 26), (16.0, 27), (12.0, 32), (8.0, 37), (8.0, 34), (8.0, 33), (8.0, 31), (8.0, 24), (4.0, 38), (4.0, 29), (4.0, 25)]
console.log(statistics.describe())
Count: 25
Sum: 744
Min: 24
Max: 38
Range: 14
Mean: 30
Median: 29
Mode: (26, 5)
Variance: 17.5
Standard Deviation: 4.2
Frequency Distribution: [(20.0, 26), (16.0, 27), (12.0, 32), (8.0, 37), (8.0, 34), (8.0, 33), (8.0, 31), (8.0, 24), (4.0, 38), (4.0, 29), (4.0, 25)]
① count, sum, min, max, range
const statistics = {};
statistics.count = (arr) => arr.length;
statistics.sum = (arr) => arr.reduce((a, b) => a + b);
statistics.min = (arr) => Math.min(...arr);
statistics.max = (arr) => Math.max(...arr);
statistics.range = (arr) => Math.max(...arr) - Math.min(...arr);
② mean : an average of a data set
statistics.mean = (arr) => {
const sum = arr.reduce((a, b) => a + b);
const count = arr.length;
// need to return explicitly
return Math.round(sum / count);
}
console.log('Mean: ', statistics.mean(ages));
// Mean: 30
③ median : the middle value when a data set is sorted
If the length of a set is an odd number, it’s the middle value. If not, it’s an average of two values in the middle.
statistics.median = (arr) => {
let median;
const sortedArr = arr.sort((a, b) => a - b);
if (arr.length % 2 != 0) {
median = sortedArr[(arr.length - 1) / 2];
} else {
median = (sortedArr[(arr.length / 2) - 1] + sortedArr[arr.length / 2]) / 2;
}
return median;
}
console.log('Median: ',statistics.median(ages));
// Median: 29
④ mode : the most common number in a set
statistics.mode = (arr) => {
const num = [...new Set(arr)];
const count = num.map((element) =>
arr.filter((number) => number === element).length)
let max = Math.max(...count);
let object = {};
object.mode = num[count.indexOf(max)];
object.count = max;
return object;
}
console.log('Mode: ', statistics.mode(ages));
// {mode: 26, count: 5}
⑤ variance : how to calculate the variance
1) Find a mean.
2) Find each score’s deviation from the mean.
3) Square each deviation from the mean.
4) Find the sum of squares.
5) Divide the sum of squares by n-1(sample) or N(population).
+) A population is the entire group that you want to draw conclusions about. A sample is the specific group that you will collect data from. The size of the sample is always less than the total size of the population.
statistics.var = (arr) => {
const sum = arr.reduce((a, b) => a + b);
const count = arr.length;
const mean = sum / count;
const deviation = arr.map((element) => element - mean);
const square = deviation.map((num) => num * num);
const sumOfSquares = square.reduce((a, b) => a + b);
return +(sumOfSquares / count).toFixed(1);
}
console.log('Variance: ',statistics.var(ages));
// Variance: 17.5
⑥ standard deviation : how to calculate the standard deviation
Basically it’s a square-rooted variance.
1) Find a mean. 2) For each data point, find the square of its distance to the mean. 3) Sum the values from Step 2. 4) Divide by the number of data points. 5) Take the square root.
statistics.std = (arr) => {
const sum = arr.reduce((a, b) => a + b);
const count = arr.length;
const mean = sum / count;
const deviation = arr.map((element) => element - mean);
const square = deviation.map((num) => num * num);
const sumOfSquares = square.reduce((a, b) => a + b);
const variance = sumOfSquares / count;
return +(Math.sqrt(variance).toFixed(1));
}
console.log('Standard Deviation: ', statistics.std(ages));
// Standard Deviation: 4.2
⑦ frequency distribution : how to calculate frequency distribution
1) Calculate the range of the data set.
2) Divide the range by the number of groups you want and then round up.
3) Use the class width to create your groups.
4) Find the frequency for each group.
const num = [...new Set(arr)];
const freqDist = [];
num.forEach((unique) => {
let frequency;
let times = arr.filter((element) =>
element === unique).length;
frequency = `(${(times / arr.length) * 100}, ${unique})`;
freqDist.push(frequency);
})
statistics['frequency distribution'] = [freqDist.join(', ')];
toFixed()
sets the decimal points of the number and rounds the number. A thing to consider is that it returns a number in the type of a string.
Math.round()
,Math.floor()
,Math.ceil()
all round the number into nearest ‘integer.’
Leave a comment