Array Data Structure in JavaScript — Search, Sort, Filter, Map, & Reduce

Check the Previous Array article

This article is Part II of the initial array data structure introductory article you must check to understand how it works and much more.

Searching and Finding Array Items

You can access any item if you know their address — aka index — but sometimes you don’t know at which index the item is so you need to find it. Other times you just want to know at which index the item is and for both of the situations, the JavaScript array comes with the “find” and the “findIndex” for the job.

const todoItems = [
{id: 0, title: 'pick kids at school'},
{id: 1, title: 'go to the gym'},
{id: 45, title: 'study for the exam'}
];
todoItems.find(todo => todo.id === 45);
// returns
// { id: 45, title: 'study for the exam' }
todoItems.findIndex(todo => /gym/g.test(todo.title));
// returns 1
const numbers = [45, 12, 99, 2, 10, 78, 34];function findAll(list, cb) {
const matches = [];
let i = 0;

for(const item of list) {
if(cb(item, i, list)) {
matches.push(item)
}
i++;
}

return matches;
}
findAll(numbers, n => n > 50);
// returns [ 99, 78 ]

Checking if Array contains certain Items

There will be situations in which you simply want to confirm that a certain item is in the array and don’t care where. You can use the find methods you learned above to check if they return something different than “undefined” or “-1” to confirm but there is a better way for that. The Array comes with the “includes”, “indefOf”, and “lastIndexOf” methods for the job.

const numbers = [45, 12, 99, 2, 10, 78, 34];numbers.includes(99); // true
numbers.includes(300); // false
numbers.indexOf(99); // 2
numbers.indexOf(300); // -1
const gymTodo = {id: 1, title: 'go to the gym'};const todoItems = [
{id: 0, title: 'pick kids at school'},
{id: 45, title: 'study for the exam'},
gymTodo
];
todoItems.includes({id: 1, title: 'go to the gym'}); // false
todoItems.includes(gymTodo); // true
todoItems.indexOf({id: 1, title: 'go to the gym'}); // -1
todoItems.indexOf(gymTodo); // 2
const numbers = [45, 12, 99, 2, 10, 45, 78, 34];numbers.indexOf(45); // 0
numbers.lastIndexOf(45); // 5
numbers.indexOf(45, 5);
// starts looking from index 5
// to the end of the array
// returns 5
numbers.lastIndexOf(45, 4);
// starts looking from index 4
// to the beginning of the array
// returns 0
const numbers = [45, 12, 99, 56, 10, 45, 78, 34];function allIndexOf(list, index, fromIndex = 0) {
const matches = [];

while(fromIndex < list.length) {
fromIndex = list.indexOf(index, fromIndex);

if(fromIndex < 0) break;

matches.push(fromIndex);
fromIndex += 1;
}

return matches;
}
allIndexOf(numbers, 45);
// returns [ 0, 5 ]
const numbers = [45, 12, 99, 56, 10, 45, 78, 34];numbers.some(n => n === 10); // true
numbers.every(n => n > 10); // true

Sorting Array Items

The array prototype comes with the “sort” method but can give you weird results. Luckily, it accepts a callback function which you can use to gain control over the sorting. This method is not pure which means it changes your array in place even though it returns the sorted array.

const numbers = [45, 12, 99, 2, 10, 45, 78, 34];numbers.sort();
/* numbers become
[
10, 12, 2, 34,
45, 45, 78, 99
]
*/
const numbers = [45, 12, 99, 2, 10, 45, 78, 34];numbers.sort((a, b) => a - b);
/* sorts ascending
[
2, 10, 12, 34,
45, 45, 78, 99
]
*/
numbers.sort((a, b) => b - a);
/* sorts descending
[
99, 78, 45, 45,
34, 12, 10, 2
]
*/
const people = [
{name: 'A', age: 12},
{name: 'K', age: 34},
{name: 'b', age: 12},
{name: 'J', age: 24},
{name: 'A', age: 34},
{name: 'Z', age: 18},
{name: 'E', age: 56}
];
people.sort((personA, personB) => {
if(personA.age < personB.age) return -1
if(personA.age > personB.age) return 1

return 0;
});
/* people array becomes
[
{ name: 'A', age: 12 },
{ name: 'b', age: 12 },
{ name: 'Z', age: 18 },
{ name: 'J', age: 24 },
{ name: 'K', age: 34 },
{ name: 'A', age: 34 },
{ name: 'E', age: 56 }
]
*/

Reverse & Shuffle Array Items

The same way you want to sort the items in an array into a specific order you may want to also reverse the items as well as create a random order of items. The Array prototype exposes a “reverse” method but no method that allows you to shuffle.

const numbers = [45, 12, 99, 2, 10, 45, 78, 34];numbers.reverse();
/* numbers become
[
34, 78, 45, 10,
2, 99, 12, 45
]
*/
const numbers = [45, 12, 99, 2, 10, 45, 78, 34];function reverseList(list) {
const reversedList = [];

for(const item of list) {
reversedList.unshift(item);
}

return reversedList;
}
reverseList(numbers);
/* returns
[
34, 78, 45, 10,
2, 99, 12, 45
]
*/
console.log(numbers)
/* numbers dont change
[
45, 12, 99, 2,
10, 45, 78, 34
]
*/
const numbers = [45, 12, 99, 2, 10, 45, 78, 34];function shuffleList(list) {
// make a shallow copy of the list
const shuffled = [...list];

for(const index in list) {
// turn index into a number
// since it is read as string

const i = Number(index);
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}

return shuffledList;
}
const shuffledNumbers = shuffleList(numbers);
// returns a shuffled array
console.log(numbers)
/* numbers dont change
[
45, 12, 99, 2,
10, 45, 78, 34
]
*/
const ab = [3, 4];[ab[0], ab[1]] = [ab[1], ab[0]];/* ab becomes [4, 3];

Turn Array into a string

Turning an array into a string can prove to be useful in many situations. There are 3 methods we can use to do that and they all serve different purposes.

const mixArray = [12, "sample", function() {}, {test: true}];mixArray.toString();
// results in
// '12,sample,function () {},[object Object]'
const arrayWithSymbolItem = [Symbol('secret')];arrayWithSymbolItem.toString();
// throws error
// TypeError: Cannot convert a Symbol value to a string
const prices = [7, 500, 8123, 12];prices.toLocaleString(
'en-US',
{ style: 'currency', currency: 'USD' }
);
// returns
// "$7, $500.00, $8, 123.00, $12.00"
const peopleNames = ['John', 'Peter', 'Jane'];peopleNames.join(', ');
// returns: 'John, Peter, Jane'

Map & Filtering Items

Mapping is an awesome way to transform and create a new array at the same time without changing the array length. Filtering allows you to grab only the items that match your criteria. Both, “map” and “filter” methods, are pure array methods, meaning, they do not change the original array.

const numbers = [45, 12, 99, 2, 10, 45, 78, 34];const doubledNumbers = numbers.map(n => n * 2);
/* double the numbers
[
90, 24, 198, 4,
20, 90, 156, 68
]
*/
const oddNumbers = numbers.filter(n => n % 2 !== 0);
/* grab odd numbers
[ 45, 99, 45 ]
*/
// numbers remain intact
const set = new Set([34, 23, 10]);
const iterableObj = {
items: [34, 23, 10],
[Symbol.iterator]() {
const items = this.items;
return {
current: 0,
next() {
if(this.current < items.length) {
return {value: items[this.current++], done: false}
}

return {done: true}
}
}
}
}
// using the "from"
console.log(
Array.from(set, n => n * 2),
Array.from(iterableObj, n => n * 2),
Array.from('sample', n => n + '_'),
Array.from({length: 10}, (_, i) => i+1),
)
// using the "map"
console.log(
[...set].map(n => n * 2),
[...iterableObj].map(n => n * 2),
[...'sample'].map(n => n + '_'),
Array(10).fill().map((_, i) => i+1),
)
// both will produce the same arrays
const numbers = [45, 12, 99, 2, 10, 78, 34];numbers.filters(numbers, n => n > 50); 
// returns [ 99, 78 ]

Flatting Array Items

In case you have nested arrays, the Array prototype comes with the flat” method to straighten that up. It returns a new array instead of changing the original array and takes an optional argument to indicate how deep you want it to flat the array.

const numbers = [
[[34, 23], [23, 67]],
[[12, 90], [33, 53]]
];
numbers.flat();
/* returns
[
[ 34, 23 ], [ 23, 67 ],
[ 12, 90 ], [ 33, 53 ]
]
*/
numbers.flat(2);
/* returns
[
34, 23, 23, 67,
12, 90, 33, 53
]
*/
const numbers = [[[34, 23], [23, 67]], [[12, 90], [33, 53]]];numbers.flatMap(([group1, group2]) => [
group1[0] + group1[1],
group2[0] + group2[1]
]);
// returns [ 57, 90, 102, 86 ]

Reduce Array

The “reduce” method is probably the hardest one to read and one that is often questioned if it is really needed. Nonetheless, it is a super powerful method that allows you to turn your array into anything else you want. You may use to apply concepts like filtering and mapping which makes it the most powerful and flexible Array method.

const numbers = [45, 12, 99, 2, 10, 78, 34];numbers.reduce((accumulator, number) => {
return accumulator + number;
}, 0);
// returns 280
const numbers = [45, 12, 99, 2, 10, 78, 34];// same as second argument in "reduce" call
let accumulator = 0;
// reduce loops the array
for(const number of numbers) {
// same as return
accumulator
+= number;
}
console.log(accumulator); // 280
const numbers = [45, 12, 99, 2, 10, 78, 34];numbers.reduce((acc, number) => {
if(number % 2 === 0) {
acc.even.push(number);
} else {
acc.odd.push(number);
}

return acc;
}, {odd: [], even: []});
/* returns
{
odd: [ 45, 99 ], even: [ 12, 2, 10, 78, 34 ] }
*/

Array methods “this” bind

During this article, you got exposed to a lot of array methods and most of them take a callback function, for example, “map”, “forEach”, “flat”, etc. What I did not mention is that some of them that take a callback also take a second argument which is the object to bind to the callback you passed.

class Calculator {
total = 0;

add(x = 0) {
this.total += x;
}

subtract(x = 0) {
this.total -= x;
}

divide(x = 0) {
this.total /= x;
}

multiply(x = 0) {
this.total *= x;
}

clear() {
this.total = 0;
}
}
const calc = new Calculator();
const numbers = [45, 12, 99, 2, 10, 78, 34];
numbers.forEach(calc.add, calc);calc.total // 280calc.clear();numbers.map(function(n) {
this.clear();
this.add(n);
this.multiply(3);
this.divide(2);

return this.total;
}, calc);
/* returns
[
67.5, 18, 148.5,
3, 15, 117, 51
]
*/

Conclusion

The array data structure is simple, powerful, and rich. Every programming language provides its version of some or most of these methods to deal with an indexed list. JavaScript arrays are particularly fun to work with and one you should feel comfortable working with in general.

Blog & YouTube Channel for Web, UI & Software Development - beforesemicolon.comyoutube.com/c/BeforeSemicolon

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