Real Examples of Javascript Functional Programming for Beginners

Disclaimer:
This story was written during dark times. It may be a bit sarcastic but my heart was in the right place, I just wanted to write an introduction to functional programming with concrete examples.

Let’s put some context

const users = [
{
id: 4545,
nickname: "franky",
name: "Frank",
email: "frank4545@aol.com",
country: "US",
subscriber: true
},
{
id: 4546,
nickname: "castortroy",
name: "Troy",
email: "realtroy@gg.com",
country: "US",
subscriber: false
},
{
id: 4547,
nickname: "melly99",
name: "melody",
email: "darkistheday@cusual.io",
country: "IT",
subscriber: false
}
];

Introduction to the Map function

const users_without_extra_info = [];
for (user of users) {
users_without_extra_info.push({
name: user.name,
email: user.email
});
}
[
{ name: "Frank", email: "frank4545@aol.com" },
{ name: "melody", email: "darkistheday@cusual.io" },
{ name: "Troy", email: "realtroy@gg.com" }
];
const users_with_map = users.map(user => {
return {
name: user.name,
email: user.email
};
});
console.log(users_with_map);
[
{ name: "Frank", email: "frank4545@aol.com" },
{ name: "melody", email: "darkistheday@cusual.io" },
{ name: "Troy", email: "realtroy@gg.com" }
];
function userWitoutExtratInfo(user) {
return {
name: user.name,
email: user.email
};
}
users.map(userWitoutExtratInfo); // no suprise it also returns
// [ { name: 'Frank', email: 'frank4545@aol.com' },
// { name: 'melody', email: 'darkistheday@cusual.io' },
// { name: 'Troy', email: 'realtroy@gg.com' } ]
const users_for_angela_with_map = users.map(user => {
return {
name: user.name,
email: user.email
};
});
// VS
const users_for_angela = []; // not needed with map() (it return a new array)
for (user of users) {
// With map() I don't need to botter choosing how to loop over it, and I can't make mistakes
users_for_angela.push({
// here it's pretty much the same but I can't make the mistake of modifying my original array
name: user.name,
email: user.email
});
}

How to Filter using ‘filter’ function

Angela: THERE IS A BIG PROBLEM WITH THE LIST YOU GAVE ME. ALL THE EMAIL I SENT TO AOL EMAIL CAME BACK TO ME… YOU MUST HAVE GIVEN ME WRONG EMAIL.
Me: Yeah AOL close years ago. I will give you the list purged of AOL’s address give me 30 minutes it’s coffee time
Angela: YOU ARE GOING ON BREAK ? BUT YOU JUST ARRIVED
Me: Exactly I just arrived. I need some coffee
(see gave me that fake smile again — I replied with my poker face of the casual days)

const users_no_aol = [];
for (user of users) {
if (!user.email.includes("aol.com")) {
// RIP AOL
users_no_aol.push({
name: user.name,
email: user.email
});
}
}
console.log(users_no_aol); // it prints:
// [ { name: 'melody', email: 'darkistheday@cusual.io' },
// { name: 'Troy', email: 'realtroy@gg.com' } ]
const all_users = users.map(user => {
return {
name: user.name,
email: user.email
};
});
const users_with_aol_filtered = all_users.filter(user => {
return !user.email.includes("aol.com");
});
console.log(users_with_aol_filtered); // and it prints:
// [ { name: 'melody', email: 'darkistheday@cusual.io' },
// { name: 'Troy', email: 'realtroy@gg.com' } ]
const all_users_for_angela = users.map(user => {
return {
name: user.name,
email: user.email
};
});
const users_aol_filtered = all_users_for_angela.filter(user => {
return !user.email.includes("aol.com");
});
// VS
const users_no_aols = [];
for (user of users) {
if (!user.email.includes("aol.com")) {
// it take only this line to filter with our for loop
users_no_aols.push({
name: user.name,
email: user.email
});
}
}
users
.map(user => {
return {
name: user.name,
email: user.email
};
})
.filter(user => {
return !user.email.includes("aol.com");
}); // and filter returns:
// [ { name: 'melody', email: 'darkistheday@cusual.io' },
// { name: 'Troy', email: 'realtroy@gg.com' } ]
users
.map(user => {
return { name: user.name, email: user.email }; // sometime one line code is better
})
.filter(user => {
return !user.email.includes("aol.com");
}); // same return returned by filter
// [ { name: 'melody', email: 'darkistheday@cusual.io' },
// { name: 'Troy', email: 'realtroy@gg.com' } ]

Sort function a concrete example

users
.map(user => {
return { name: user.name, email: user.email };
})
.filter(user => {
return !user.email.includes("aol.com");
})
.sort((userA, userB) => {
if (userA.name.toLowerCase() < userB.name.toLowerCase())
return -1;
if (userA.name.toLowerCase() > userB.name.toLowerCase())
return 1;
return 0;
});
// sort returns :
// [ { name: 'melody', email: 'darkistheday@cusual.io' },
// { name: 'Troy', email: 'realtroy@gg.com' } ]

Me: There you go. Here is the list.
Angela: Mhmm let me see… I would like to start from the bottom of the list and remove user one by one. But I can’t because it’s in the wrong order.
Me:
Me: No problem just give me 1 hour :-)

users
.map(user => {
return { name: user.name, email: user.email };
})
.filter(user => {
return !user.email.includes("aol.com");
})
.sort((userA, userB) => {
if (userA.name.toLowerCase() < userB.name.toLowerCase())
return -1;
if (userA.name.toLowerCase() > userB.name.toLowerCase())
return 1;
return 0;
})
.reverse(); // yep reverse ! No need to modify any thing to return:
// [ { name: 'Troy', email: 'realtroy@gg.com' },
// { name: 'melody', email: 'darkistheday@cusual.io' } ]

Angela: But also need the user nickname dummy !

users
.map(user => {
return { name: user.name, email: user.email, nickname: user.nickname }; // here goes your dummy nickname
})
.filter(user => {
return !user.email.includes("aol.com");
})
.sort((userA, userB) => {
if (userA.name.toLowerCase() < userB.name.toLowerCase())
return -1;
if (userA.name.toLowerCase() > userB.name.toLowerCase())
return 1;
return 0;
})
.reverse(); // returns
// [ { name: 'Troy',
// email: 'realtroy@gg.com',
// nickname: 'castortroy' },
// { name: 'melody',
// email: 'darkistheday@cusual.io',
// nickname: 'melly99' } ]

Angela: Price just told me that AOL hasn’t closed. Is just that today they have server issues so I need them back
Me: If you say so…

users
.map(user => {
return { name: user.name, email: user.email, nickname: user.nickname };
}) // no more filter (isn't it nice to delete consecutive lines and get a new feature ?!)
.sort((userA, userB) => {
if (userA.name.toLowerCase() < userB.name.toLowerCase())
return -1;
if (userA.name.toLowerCase() > userB.name.toLowerCase())
return 1;
return 0;
})
.reverse();

Angela: Thank you very much! Is it possible to get the name in big letters and the nickname with little letter ?
Me: You mean in UPPERCASE and in lowercase ?
Angela: Yes! So Is it possible ?
Me: Nothing is impossible except to work in this company for free.

users
.map(user => {
return { name: user.name, email: user.email, nickname: user.nickname };
})
.sort((userA, userB) => {
if (userA.name.toLowerCase() < userB.name.toLowerCase())
return -1;
if (userA.name.toLowerCase() > userB.name.toLowerCase())
return 1;
return 0;
})
.reverse()
.map(user => {
// could have been this above In the first map, but Angela could change one more time
return {
...user,
name: user.name.toUpperCase(),
nickname: user.nickname.toLowerCase()
};
})
; // returns:
// [ { name: 'TROY',
// email: 'realtroy@gg.com',
// nickname: 'castortroy' },
// { name: 'MELODY',
// email: 'darkistheday@cusual.io',
// nickname: 'melly99' },
// { name: 'FRANK', email: 'frank4545@aol.com', nickname: 'franky' } ]

Angela: There is a big problem! Hank just told me I need a CSV file!
Me: CSV you sure he didn’t say JSON file ?
Angela: CSV I’m sure I wrote it down on this pink post-it
Me: Isn’t purple ?

let user_csv = users
.map(user => {
return {
name: user.name.toUpperCase(), // I bet she won't care about this anymore (It's almost the end of the day afterall)
email: user.email,
nickname: user.nickname.toLowerCase()
};
})
.sort((userA, userB) => {
if (userA.name.toLowerCase() < userB.name.toLowerCase())
return -1;
if (userA.name.toLowerCase() > userB.name.toLowerCase())
return 1;
return 0;
})
.reverse()
.map(user => Object.values(user).join(";")); // join each value of the user object with ";"
console.log(user_csv); // prints:
// [ 'TROY;realtroy@gg.com;castortroy',
// 'MELODY;darkistheday@cusual.io;melly99',
// 'FRANK;frank4545@aol.com;franky' ]

Me: Whoops I forgot to put a semi column at the end of each line!
Angela: Hurry up!! it’s almost closing time and I still haven’t sent my newsletter today…

users
.map(user => {
return {
name: user.name.toUpperCase(),
email: user.email,
nickname: user.nickname.toLowerCase()
};
})
.sort((userA, userB) => {
if (userA.name.toLowerCase() < userB.name.toLowerCase())
return -1;
if (userA.name.toLowerCase() > userB.name.toLowerCase())
return 1;
return 0;
})
.reverse()
.map(user => Object.values(user).join(";"))
.map(csv_line => csv_line + ";"); // I could have done it one line before. But I like this way. One operation by map
// our last map returns:
// [ 'TROY;realtroy@gg.com;castortroy;',
// 'MELODY;darkistheday@cusual.io;melly99;',
// 'FRANK;frank4545@aol.com;franky;' ]
let whole_csv_string = "";
for (const line of toto) {
whole_csv_string = whole_csv_string + "\n" + line;
}
console.log(whole_csv_string); // prints:
// TROY;realtroy@gg.com;castortroy;
// MELODY;darkistheday@cusual.io;melly99;
// FRANK;frank4545@aol.com;franky;
proper_csv = my_list.reduce((whole_csv, csv_line) => whole_csv + "\n" + csv_line);
console.log(proper_csv); // prints:
// TROY;realtroy@gg.com;castortroy;
// MELODY;darkistheday@cusual.io;melly99;
// FRANK;frank4545@aol.com;franky;

Me: Mission accomplish !
Angela: Stop bragging. Give me the list.

A bit of functional programming theory :

Summary:

Conclusion:

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store