Here’s what I came up with for the JavaScript version of the Hurricanes project:
Some of the tasks seemed repetitive, so I made some utility functions that could handle both objects and arrays.
The names for the functions are unusual for JavaScript because I took them from the my Python version for this project.
// names of hurricanes
const names = ['Cuba I', 'San Felipe II Okeechobee', 'Bahamas', 'Cuba II', 'CubaBrownsville', 'Tampico', 'Labor Day', 'New England', 'Carol', 'Janet', 'Carla', 'Hattie', 'Beulah', 'Camille', 'Edith', 'Anita', 'David', 'Allen', 'Gilbert', 'Hugo', 'Andrew', 'Mitch', 'Isabel', 'Ivan', 'Emily', 'Katrina', 'Rita', 'Wilma', 'Dean', 'Felix', 'Matthew', 'Irma', 'Maria', 'Michael'];
// months of hurricanes
const months = ['October', 'September', 'September', 'November', 'August', 'September', 'September', 'September', 'September', 'September', 'September', 'October', 'September', 'August', 'September', 'September', 'August', 'August', 'September', 'September', 'August', 'October', 'September', 'September', 'July', 'August', 'September', 'October', 'August', 'September', 'October', 'September', 'September', 'October'];
// years of hurricanes
const years = [1924, 1928, 1932, 1932, 1933, 1933, 1935, 1938, 1953, 1955, 1961, 1961, 1967, 1969, 1971, 1977, 1979, 1980, 1988, 1989, 1992, 1998, 2003, 2004, 2005, 2005, 2005, 2005, 2007, 2007, 2016, 2017, 2017, 2018];
// maximum sustained winds (mph) of hurricanes
const max_sustained_winds = [165, 160, 160, 175, 160, 160, 185, 160, 160, 175, 175, 160, 160, 175, 160, 175, 175, 190, 185, 160, 175, 180, 165, 165, 160, 175, 180, 185, 175, 175, 165, 180, 175, 160];
// areas affected by each hurricane
const areas_affected = [['Central America', 'Mexico', 'Cuba', 'Florida', 'The Bahamas'], ['Lesser Antilles', 'The Bahamas', 'United States East Coast', 'Atlantic Canada'], ['The Bahamas', 'Northeastern United States'], ['Lesser Antilles', 'Jamaica', 'Cayman Islands', 'Cuba', 'The Bahamas', 'Bermuda'], ['The Bahamas', 'Cuba', 'Florida', 'Texas', 'Tamaulipas'], ['Jamaica', 'Yucatn Peninsula'], ['The Bahamas', 'Florida', 'Georgia', 'The Carolinas', 'Virginia'], ['Southeastern United States', 'Northeastern United States', 'Southwestern Quebec'], ['Bermuda', 'New England', 'Atlantic Canada'], ['Lesser Antilles', 'Central America'], ['Texas', 'Louisiana', 'Midwestern United States'], ['Central America'], ['The Caribbean', 'Mexico', 'Texas'], ['Cuba', 'United States Gulf Coast'], ['The Caribbean', 'Central America', 'Mexico', 'United States Gulf Coast'], ['Mexico'], ['The Caribbean', 'United States East coast'], ['The Caribbean', 'Yucatn Peninsula', 'Mexico', 'South Texas'], ['Jamaica', 'Venezuela', 'Central America', 'Hispaniola', 'Mexico'], ['The Caribbean', 'United States East Coast'], ['The Bahamas', 'Florida', 'United States Gulf Coast'], ['Central America', 'Yucatn Peninsula', 'South Florida'], ['Greater Antilles', 'Bahamas', 'Eastern United States', 'Ontario'], ['The Caribbean', 'Venezuela', 'United States Gulf Coast'], ['Windward Islands', 'Jamaica', 'Mexico', 'Texas'], ['Bahamas', 'United States Gulf Coast'], ['Cuba', 'United States Gulf Coast'], ['Greater Antilles', 'Central America', 'Florida'], ['The Caribbean', 'Central America'], ['Nicaragua', 'Honduras'], ['Antilles', 'Venezuela', 'Colombia', 'United States East Coast', 'Atlantic Canada'], ['Cape Verde', 'The Caribbean', 'British Virgin Islands', 'U.S. Virgin Islands', 'Cuba', 'Florida'], ['Lesser Antilles', 'Virgin Islands', 'Puerto Rico', 'Dominican Republic', 'Turks and Caicos Islands'], ['Central America', 'United States Gulf Coast (especially Florida Panhandle)']];
// damages (USD($)) of hurricanes
let damages = ['Damages not recorded', '100M', 'Damages not recorded', '40M', '27.9M', '5M', 'Damages not recorded', '306M', '2M', '65.8M', '326M', '60.3M', '208M', '1.42B', '25.4M', 'Damages not recorded', '1.54B', '1.24B', '7.1B', '10B', '26.5B', '6.2B', '5.37B', '23.3B', '1.01B', '125B', '12B', '29.4B', '1.76B', '720M', '15.1B', '64.8B', '91.6B', '25.1B'];
// deaths for each hurricane
const deaths = [90,4000,16,3103,179,184,408,682,5,1023,43,319,688,259,37,11,2068,269,318,107,65,19325,51,124,17,1836,125,87,45,133,603,138,3057,74];
const conversion = {
"K": 1000,
"M": 1000000,
"B": 1000000000,
"T": 1000000000000 };
function clean(place_list) {
const len = place_list.length;
for (var i = 0; i < len; i++) {
//place_list[i] = place_list[i].toLowerCase().trim()
if (place_list[i] == "The Bahamas") {
place_list[i] = "Bahamas";
}
if (place_list[i].includes('Yucatn')) {
place_list[i] = place_list[i].replace('Yucatn', 'Yucatan');
}
if (place_list[i].includes('(')) {
let open = place_list[i].indexOf('(');
let close = place_list[i].indexOf(')');
let inside = place_list[i].slice(open+1 ,close);
place_list[i] = place_list[i].slice(0, open);
if (inside.startsWith('especially')) {
inside = inside.substring(11);
}
place_list.push(inside);
}
}
let j;
j = place_list.indexOf('The Carolinas');
if (j > -1) {
place_list.splice(j, 2, 'North Carolina', 'South Carolina');
}
j = place_list.indexOf('Virgin Islands');
if (j > -1) {
place_list.splice(j, 2, 'U.S. Virgin Islands', 'British Virgin Islands');
}
j = place_list.indexOf('Antilles');
if (j > -1) {
place_list.splice(j, 2, 'Greater Antilles', 'Lesser Antilles');
}
}
for (var i = 0; i < areas_affected.length; i++) {
clean(areas_affected[i]);
}
/*
for (var areas of areas_affected) {
console.log(areas);
}
*/
function isDigits(text) {
let isAllDigits = true;
var length = text.length;
let attempt;
for (var i = 0; i < length; i++) {
attempt = text.charCodeAt(i) - 48;
if ((attempt < 0) || (attempt > 9)) {
return false;
isAllDigits = false;
break;
}
}
return isAllDigits;
}
//# 1
// Update Recorded Damages
function to_float(stuff) {
if (typeof(stuff) == 'string') {
if (Object.keys(conversion).includes(stuff[stuff.length - 1]) && isDigits(stuff[0])) {
return parseFloat(stuff.slice(0, -1)) * conversion[stuff[stuff.length - 1]];
}
else if (isDigits(stuff)) {
return parseFloat(stuff);
}
else {
return stuff;
//return parseFloat(stuff);
}
}
else if (Array.isArray(stuff)) {
return stuff.map(to_float);
}
}
damages.forEach(
(val, index, arr) =>
{ arr[index] = to_float(val); });
//console.log(damages);
//# 2
// Create a Table
let lists = [names, months, years, max_sustained_winds, areas_affected, damages, deaths];
let table = new Array(lists.length);
for (var i in names) {
table[i] = lists.map( arr => arr[i] );
}
const column_names = ['Name', 'Month', 'Year', 'Max Sustained Wind', 'Areas Affected', 'Damage', 'Deaths'];
function make_hurricane_dict(names, months, years, winds, areas, damage, deaths) {
let dictionary = {};
const transpose = [names, months, years, winds, areas, damage, deaths];
let length = names.length;
for (let i = 0; i < length; i++) {
Object.assign( dictionary, { [transpose[0][i]]:
{ 'Name': transpose[0][i],
'Month': transpose[1][i],
'Year': transpose[2][i],
'Max Sustained Wind': transpose[3][i],
'Areas Affected': transpose[4][i],
'Damage': transpose[5][i],
'Deaths': transpose[6][i]
} });
}
return dictionary;
}
let hurricanes_dict = make_hurricane_dict(names, months, years, max_sustained_winds, areas_affected, damages, deaths);
//# 3
// Organizing by Year
function group(stuff, by, index_as_key, apply) {
/* apply is a function to use on each item,
whose output will be used to group the items */
let key_for;
if ((apply == null) || !(apply)) {
key_for = x => x;
}
else if (Array.isArray(apply)) {
key_for = x => apply.indexOf(x);
}
else if (typeof(apply) == 'object') {
key_for = x => apply[x];
}
else {
key_for = apply;
}
let grouped = {};
let indecies = Object.keys(stuff);
if (by == null){
for (let i of indecies) {
let current;
//current = stuff[i]
if (apply == null) {
current = stuff[i];
}
else {
current = key_for(stuff[i]);
}
if (grouped[current] == null) {
grouped[current] = [];
}
grouped[current].push(i); //list of indecies
}
}
else {
for (let i of indecies) {
let current;
//current = stuff[i][by]
if (apply == null) {
current = stuff[i][by];
}
else {
current = key_for(stuff[i][by]);
}
let to_add;
if (index_as_key) { to_add = i; }
else { to_add = stuff[i]; }
if (grouped[current] == null) {
grouped[current] = [];
}
grouped[current].push(to_add); //list of indecies
}
}
return grouped;
}
function make_dict_by_year(data) {
return group(data, 'Year', false);
};
// create a new dictionary of hurricanes with year and key
let hurricanes_by_year = make_dict_by_year(hurricanes_dict);
//# 4
// Counting Damaged Areas
function get_freq_of_list_items_in_col(stuff, column) {
let frequencies = {};
let indecies = Object.keys(stuff);
if (column == null) {
for (var i of indecies) {
for (let this_one of stuff[i]) { // of ???
if (frequencies[this_one] == null) {
frequencies[this_one] = 1;
}
else {
frequencies[this_one] += 1;
}
}
}
}
else {
for (var i of indecies) {
for (let this_one of stuff[i][column]) { // of ???
if (frequencies[this_one] == null) {
frequencies[this_one] = 1;
}
else {
frequencies[this_one] += 1;
}
}
}
}
return frequencies;
};
let hurricane_count_by_area = get_freq_of_list_items_in_col(hurricanes_dict, 'Areas Affected');
/*
for (let area in hurricane_count_by_area) {
console.log(area + ": " + hurricane_count_by_area[area]);
}
*/
//# 5
// Calculating Maximum Hurricane Count
// function to get maximum [and its index]
// (only for numbers)
function max_of(stuff, include_index, column) {
let indecies = Object.keys(stuff);
let maximum = Math.NaN;
let index_of_max;
if (column == null) {
for (var i of indecies) {
if (typeof(stuff[i]) == 'number') {
if (isNaN(maximum)) {
maximum = stuff[i];
index_of_max = i;
}
else if (stuff[i] > maximum) {
maximum = stuff[i];
index_of_max = i;
}
}
}
}
else {
for (var i of indecies) {
if (typeof(stuff[i][column]) == 'number') {
if (isNaN(maximum)) {
maximum = stuff[i][column];
index_of_max = i;
}
else if (stuff[i][column] > maximum) {
maximum = stuff[i][column];
index_of_max = i;
}
}
}
}
if (include_index) {
return [index_of_max, maximum];
}
else {
return maximum;
}
}
function get_most_frequent_area(hurricane_dict) {
let freqs = get_freq_of_list_items_in_col(hurricane_dict, 'Areas Affected');
return max_of(freqs, true);
}
// find most frequently affected area and the number of hurricanes involved
let most_affected, most_hurricanes;
[most_affected, most_hurricanes] = get_most_frequent_area(hurricanes_dict);
console.log(`The greatest number of cat5 hurricanes was at location: ${most_affected},
number of hurricanes: ${most_hurricanes}`);
console.log(' ');
//# 6
// Calculating the Deadliest Hurricane
let deadliest_index, max_deaths, deadliest_hurricane;
[deadliest_hurricane, max_deaths] =
max_of(hurricanes_dict, true, "Deaths");
console.log("deadliest hurricane: " + deadliest_hurricane);
console.log("deaths: " + max_deaths);
console.log();
//# 7
// Rating Hurricanes by Mortality
let mortality_scale =
{ 0: 0,
1: 100,
2: 500,
3: 1000,
4: 10000 }; // */
//mortality_scale = [0, 100, 500, 1000, 10000];
function classify_into_bracket(value, brackets) {
let pairs = Object.entries(brackets);
pairs.sort();
let category, upper_bound;
for (let pair of pairs) {
[category, upper_bound] = pair;
if (value <= upper_bound) {
return category;
}
}
let lastIndex = parseInt(pairs[pairs.length-1][0]);
if (!isNaN(lastIndex)) {
return lastIndex + 1;
}
}
function classify_all(data, brackets, by) {
if (Array.isArray(data)) {
if (by == null) {
return data.map(value => classify_into_bracket(value, brackets) );
}
else {
return data.map(value => classify_into_bracket(value[by], brackets) );
}
}
else {
let returnedObject = {};
if (by == null) {
for (let value in data) {
returnedObject[value] = classify_into_bracket(data[value], brackets);
}
}
else {
for (let value in data) {
returnedObject[value] = classify_into_bracket(data[value][by], brackets);
}
}
return returnedObject;
}
}
function get_hurricane_by_severity_from_damage(storm_data) {
const classify = x => classify_into_bracket(x, damage_scale);
return group(storm_data, 'Damage', false, classify);
}
// categorize hurricanes in new dictionary with mortality severity as key
let classify = x => classify_into_bracket(x, mortality_scale)
let hurricanes_by_severity = group(hurricanes_dict, 'Deaths', false, classify);
//# 8
// Calculating Hurricane Maximum Damage
// find highest damage inducing hurricane and its total cost
let costliest_index, costliest_hurricane, max_cost;
[costliest_hurricane, max_cost] = max_of(hurricanes_dict, true, 'Damage');
console.log("costliest hurricane: " + costliest_hurricane);
console.log("damage: $" + max_cost);
console.log();
//# 9
// Rating Hurricanes by Damage
let damage_scale = {
0: 0,
1: 100000000,
2: 1000000000,
3: 10000000000,
4: 50000000000 }; // */
//damage_scale = [0, 100000000, 1000000000, 10000000000, 50000000000];
let hurricane_severity_by_damage = classify_all(hurricanes_dict, damage_scale, 'Damage');
function get_hurricane_by_severity_from_damage(storm_data) {
//const classify = x => classify_into_bracket(x, damage_scale);
const classify = x =>
(typeof(x) == "number") ? classify_into_bracket(x, damage_scale) : 0;
return group(storm_data, 'Damage', false, classify);
}
// categorize hurricanes in new dictionary with damage severity as key
hurricanes_by_severity = get_hurricane_by_severity_from_damage(hurricanes_dict);
// categorize hurricanes in new dictionary with damage severity as key
classify = x =>
(typeof(x) == "number") ? classify_into_bracket(x, damage_scale) : 0;
hurricane_by_severity = group(hurricanes_dict, 'Damage', false, classify);
// display hurricanes_by_severity
console.log("hurricanes by category according to damage scale:")
for (let category in hurricanes_by_severity) {
let line = category + ": [";
let namesList = [];
for (let storm of hurricanes_by_severity[category]) {
namesList.push(storm['Name']);
}
line += namesList.join(", ") + "]";
console.log(line);
}
Here’s the stuff I made to test my code. (It also includes a lot of functions that I didn’t use in the final version of the project).
link: https://www.codecademy.com/workspaces/61400c1d6b00c4963fb899f6
If you have any comments or suggestions, please reply.