There are no shortcuts to becoming a great problem solver(which is what a dev is).
Mastery comes at the cost of practice. And since algorithms and data structures form the backbone of every software, practicing them should be on top of your priority queue. As the most used data structure for storing a sequence of values, arrays are as essential as they can be.
Today we'll hone our skills by learning how to:
*Flatten an array
*Remove duplicates from an array
*Remove duplicates from an array of objects
*Sort an array of objects
*Merge 2 arrays
*Return the difference between two arrays
*Check if an array contains duplicate elements
*Return the Intersection of two arrays
*Find the Longest String in an Array
As the old saying goes "practice makes perfect". Let's crack it.
How to flatten an array:
The easiest way is to use the built-in .flat() method.
The flat() method takes an optional maximum depth parameter.
For example, given the following array:
const arr = [1, 2, [3, 4], [[5, 6], [7, 8]]];
You can flatten it like this:
const flattened = arr.flat(2); //max depth
console.log(flattened); // [1, 2, 3, 4, 5, 6, 7, 8]
The flat() method returns a new array with all sub-arrays concatenated into it recursively up to the specified depth.
You can also create your own recursive function that iterates over the elements of the array and adds them to a new array, one at a time.
- If an element is an array, the function should call itself with the element as an argument, and then concatenate the resulting array to the new array.
- If an element is not an array, the function should simply add it to the new array.
Here is an example of how you could write a recursive function to flatten an array:
function flatten(arr) {
let result = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]));
} else {
result.push(arr[i]);
}
}
return result;
}
const arr = [1, [2, [3, [4]]], 5];
console.log(flatten(arr)); // [1, 2, 3, 4, 5]
You can make this function more concise by using the .reduce() method and the ternary operator.
function flatten(arr) {
return arr.reduce((accumulator, currentItem) =>
Array.isArray(currentItem)
? accumulator.concat(flatten(currentItem))
: accumulator.concat(currentItem),
[]);
}
If you need a refresher on the .reduce() check this guide -> https://dev.to/gustavupp/a-complete-guide-to-javascripts-reduce-function-with-real-world-examples-5h6k
This function has a linear time complexity(which means that it is efficient for large arrays).
It also has a constant space complexity(which means that it does not use up more memory as the size of the array increases).
How to remove duplicates from an array:
By far the easiest and more concise way of removing duplicates of an array is by using the Set object.
The Set object stores only unique values, so you can create a new set from the array and then use the Array.from() method to convert the set back into an array.
This is one way you can do it using the Set object:
const arr = [1, 2, 3, 1, 2, 3, 4, 5];
const unique = Array.from(new Set(arr));
console.log(unique); // [1, 2, 3, 4, 5]
You can also use our loved .reduce() (what can't you do with the reduce?? lol)
const arr = [1, 2, 3, 1, 2, 3, 4, 5]
arr.reduce((accumulator, currentItem) => {
if (!accumulator.includes(currentItem))
accumulator.push(currentItem)
return accumulator
},[])
How to sort an array of objects
To sort an array of objects you have to choose a property from the object to sort the array by.
You can then call .sort() and pass it a comparator function.
This is how the comparator function works:
- It takes two arguments
- If the first should come before the second it returns a negative value.
- If the first should come after the second it returns a positive value
- It returns 0 if the values are equal.
Here's how you could sort an array of objects by the value of the name property:
const arr = [
{name: 'Bob', age: 30},
{name: 'Alice', age: 25},
{name: 'Charlie', age: 35}
];
arr.sort((a, b) => {
if (a.age < b.age) { //you can sort by any property
return -1;
} else if (a.age > b.age) {
return 1;
} else {
return 0;
}
});
/*
[
{name: 'Alice', age: 25},
{name: 'Bob', age: 30},
{name: 'Charlie', age: 35}
] */
You can also use the ternary operator to make a one-liner version:
arr.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
Note: Sometimes nested ternaries can be hard to read.
- If sorting by a
string
it's better to use the .localeCompare() method:
arr.sort((a, b) => a.name.localeCompare(b.name));
Keep in mind that the sort() method modifies the original array, so if you want to preserve the original array, you should make a copy of it first.
How to merge 2 arrays
To merge two arrays you can use the concat() method.
The concat() method returns a new array that includes the elements from both arrays.
Here is an example of how you could use concat() to merge two arrays:
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const merged = arr1.concat(arr2);
console.log(merged); // [1, 2, 3, 4, 5, 6]
A fancier or rather an ES6 version uses the spread operator (...).
The spread operator expands the elements of an array into separate arguments.
This is how it would look like
const merged = [...arr1, ...arr2];
console.log(merged); // [1, 2, 3, 4, 5, 6]
Both of these approaches:
- Create a new array that includes the elements from both arrays
- Do not modify the original array.
If modifying the array is not an issue you can simply use .push() to add the elements of the other array to the end of the first array.
arr1.push(...arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]
Return the difference between 2 arrays
There are kinds of differences:
- Non-symmetric
- Symmetric
Non-symmetric
- Elements that are in the first array but not in the second
Symmetric
- Elements that are in the first array but not in the second, and elements that are in the second but not in the first
Here is how you can use the filter() method to find the non-symmetric difference between two arrays:
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];
const difference = arr1.filter(x => !arr2.includes(x));
console.log(difference); // [1, 2]
And this is to get the symmetric difference:
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];
const difference = arr1
.filter(x => !arr2.includes(x))
.concat(arr2.filter(x => !arr1.includes(x)));
console.log(difference); // [1, 2, 6, 7]
This approach returns a new array and does not modify the original arrays.
Alternatively, you can use the Set object and its .has() instead of .includes()
Non-symmetric difference:
const set = new Set(arr2);
const difference = arr1.filter(x => !set.has(x));
console.log(difference); // [1, 2]
Symmetric difference:
const set = new Set(arr2);
const set1 = new Set(arr1)
const difference = arr1
.filter(x => !set.has(x))
.concat(arr2.filter(x => !set1.has(x)));
console.log(difference); // [1, 2, 6, 7]
how to Check if an array contains duplicate elements
The simplest way of doing this is by using the Set object and the size property.
The Set object stores only unique values, so you can create a set from the array and compare the size of the set to the size of the original array.
If the size of the set is smaller than the size of the array, it means that the array contains duplicate elements.
Here's how you'd do it:
const arr = [1, 2, 3, 4, 5, 5];
const hasDuplicates = new Set(arr).size !== arr.length;
console.log(hasDuplicates); // true
You can achieve the same with an object(also called a hash or dictionary)
As you loop through the array you set the current value as the key
and true
as the keys' value.
If you try to access a key
and there is already a value there, it means you found a duplicate.
This is a way of doing it:
const hasDuplicates = (arr) => {
let hash = {}
for(let i = 0; i < arr.length; i++){
if(!hash[arr[i]]){
hash[arr[i]] = true
} else {
return true;
}
}
return false
}
console.log(hasDuplicates(arr)); // true
Both of these approaches create a new object (a set or a hash object) and do not modify the original array.
They also have a linear time complexity(they are efficient for large arrays).
How to return the intersection between 2 arrays
The most common way would be by using the filter() and includes().
It would look something like this:
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];
const intersection = arr1.filter(x => arr2.includes(x));
console.log(intersection); // [3, 4, 5]
This approach returns a new array and does not modify the original arrays.
As an alternative, you can use the Set object(again) and the .has() method
const set = new Set(arr2);
const intersection = arr1.filter(x => set.has(x));
console.log(intersection); // [3, 4, 5]
Do you see a pattern? Whenever work something out with a plain object you can create a version using the Set Object and vice versa.
How to find the longest string in an array
To do so, you can use our popular .reduce() method and a function to compare the values.
The comparator function will compare the length of the current string to the length of the previous longest string, and return the current string if it is longer, or the previous longest string if it is not.
This is how you can do it:
const arr = ['short', 'medium', 'long', 'longest'];
const longest = arr.reduce((acc, x) => x.length > acc.length ? x : acc, '');
console.log(longest); // 'longest'
This approach creates a new variable (the acc or accumulator) and does not modify the original array.
The time complexity is linear (meaning that it is efficient for large arrays).
The same can be achieved by using the sort() method and the spread operator (...) to find the longest string in an array more concisely:
const longest = [...arr].sort((a, b) => b.length - a.length)[0];
console.log(longest); // 'longest'
Conclusion
In this article we have learned how to:
*Flatten an array
*Remove duplicates from an array
*Remove duplicates from an array of objects
*Sort an array of objects
*Merge 2 arrays
*Return the difference between two arrays
*Check if an array contains duplicate elements
*Return the Intersection of two arrays
*Find the Longest String in an Array
Thanks for reading!
If you like this article:
*Leave a comment below(You can just say hi!)
*Follow me on Twitter @theguspear.
Catch you later,
Gus.
Top comments (6)
For smart alphabetical comparison, it's best to use
String#localeCompare
.Sorted with
>
and<
:Sorted with
String#localeCompare
:Thanks for taking the time to leave a comment @lionelrowe !
I had completely forgotten the
.localeCompare()
(in spite of having used it a few times).I updated the example to use a
number
property and gave an additional example if sorting bystring
.Thanks for contributing!
Have a great week
Your post inspired me to look into
localeCompare
a bit more β turns out it's even cooler than I thought and can be customized with options as well as a specific locale.That's awesome lionel!
I had briefly seen all the options on MDN but it was a bit too dense for this post.
And your one about Proxies did the same to me haha
Hi Gus,
Really like the post. Here is another way to perform the sort comparison.
It even returns zero is a and b have the same name.
Best regards
Hey Gilmore, I am so glad you liked it.
You not only took the time to leave a comment but also contributed to the post.
It's an honor to see a dev with your experience show up in the comment section of one of my humble posts.
I hope to see you around again.
All the best.
Gus