Ep.2 Data Structures and Algorithms with JS - Arrays

Cover Image for Ep.2 Data Structures and Algorithms with JS - Arrays

This post is part of the series: Data Structures and Algorithms with JS therefore before continue to read I suggest you the introduction to this series of posts if you haven't read yet. Thanks.

Brushing up on Arrays

This is the second post on the series of Data Structure and Algorithms with JS - focused on Array.
Notice that this is a overview/start point for those that need to brush up your knowledge on Arrays where we are going to be using in the future on more complex topics.

Every programming language has sort of a built-in Array where you can access data via index and most of these languages has a strict type of Array which would be integer BUT not in Javascript, where Array is also an object which when integers used for index they are converted to strings.
And Array being an object means that it contain properties and functions you can use out of the box.

In Javascript we don't need to define the length of our Array as in C++ and we can have different types of values therefore making Arrays in Javascript flexible and easier to manipulate than other classic languages.

Creating Arrays

Let's create an Array with length zero:

var arr = []; // arr.length = 0

Now let's create an Array with some elements defined and length equal 5:

var arr = ['a', 'b', 'c', 'd', 'e']; // arr.length = 5

Array with different types would look like:

var arr = ['michael', 'lancaster', 23, true, null];

If you want to verify if an object is an Array you can use the method Arrays.isArray()

var arr = ['a', 'b', 'c', 'd', 'e'];
Array.isArray(arr); // true

var str = 'Michael Lancaster';
Array.isArray(str); // false

Accessing

Use the operator [] passing the index to access the value/element.

var arr = ['a', 'b', 'c', 'd', 'e'];
console.log( arr[2] ) // c
console.log( arr[4] ) // e

Also iterating through an Array sequentially

var arr = [1, 2, 3, 4, 5];
for ( var i = 0; i < arr.length; i++ ) {
    console.log('Index: ' + i, 'Value: ' + arr[i])
}

// outputs
// Index: 0 Value: 1
// Index: 1 Value: 2
// Index: 2 Value: 3
// Index: 3 Value: 4
// Index: 4 Value: 5 

Notice on the sample above that the loop is controlled by the length of the Array arr.length since in Javascript Array is an object and it can be modified so we guarantee that we have gone through all indexes.

Array from String

We can also create Arrays from strings defining a delimiter (space in my case).

var str = 'Michael lancaster 23 and developer';
var arr = str.split(' '); // ["Michael", "lancaster", "23", "and", "developer"]

Object Copy

There's several ways of Object copy Shallow Copy, Deep Copy and Lazy Copy.

The Shallow Copy is when you assign "B = A" which has the disadvantage of when updating Array A the Array B will also be modified with same updates as A no matter what. Here's an example of Shallow Copy.

var arr1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var arr2 = arr1;
console.log(arr2) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
arr1.push('michael');
console.log(arr1) // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "michael"]
console.log(arr2) // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "michael"]

When we pushed a new value to the end of arr1 this change is reflected into arr2.

A better way to do a copy would be the Deep Copy which one don't depend on another but it's a slower operation.
Here's an example of Deep Copy

var arr1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var arr2 = [];

function deepCopy(arr1, arr2) {
    for ( var i = 0; i < arr1.length; i++ ) {
        arr2[i] = arr1[i];
    }
}

deepCopy(arr1, arr2);

console.log(arr1) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(arr2) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
arr1.push('michael')
console.log(arr1) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "michael"] 
console.log(arr2) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In the example above you can notice that the value pushed to arr1 do not reflected into arr2. Now. Lazy Copy is the combination of both operations.

Array traversal and mutation operations

Array is list-like and also a constructor that contains prototype methods to perform traversal and mutation operations such as:

Searching a value

Searching a value can be done with the method Array.prototype.indexOf() which perform an operation of comparing with === the value passed to the function is found and return it's index position otherwise will return -1.

var languages = ['Javascript', 'Java', 'C++', 'Go'];
languages.indexOf('C++') // 2

Notice that this search operation using the indexOf will return the just the position of the first value encountered in the Array. You can also the 'lastIndexOf' which will do the same but return the position of the last value encountered.

var languages = ['Javascript', 'Java', 'C++', 'Go', 'Lua', 'C++'];
languages.lastIndexOf('C++') // 5

String from Arrays

There's two methods to return a string representation from an Array Array.prototype.join() and Array.prototype.toString().
It's automatically delimited by commas but you can pass your delimiter on the method. Here's an example using join and toString.

var languages = ['Javascript', 'Java', 'C++', 'Go', 'Lua'];
languages.join(); // "Javascript,Java,C++,Go,Lua"
languages.toString(); // "Javascript,Java,C++,Go,Lua"

New Array from Array

There's also multiple methods to create an Array from another Array Array.prototype.concat() and Array.prototype.splice(). The Array.prototype.concat() method allow you to pass one or more Arrays/Values as argument to create a new Array.

var cats = ['Abyssinian', 'Persian', 'Peterbald'];
var dogs = ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];
var birds = ['Malleefowl', 'Maleo'];

var petAnimals = cats.concat(dogs, birds);
console.log(petAnimals); // ["Abyssinian", "Persian", "Peterbald", "Alaskan Klee Kai", "American Bulldog", "Pitbull", "Malleefowl", "Maleo"];

The Array.prototype.splice() takes two arguments (minimum) or more. You can also use to add new elements to the middle of an Array.
They are going to be used to mutate the Array therefore it can add new elements and/or remove old elements.

var dogs = ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];
var removedDogs = dogs.splice(2, 0, "Bull Terrier");
console.log(dogs); // ["Alaskan Klee Kai", "American Bulldog", "Bull Terrier", "Pitbull"]
console.log(removedDogs); // [] empty since no values/elements were removed

Above the order of my arguments are .splice(from index, remove, enter new element) so looking at my arguments we have inserted a new value Bull terrier removed 0 and started at index 2.

var dogs = ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];
var removedDogs = dogs.splice(1, 1, "Bull Terrier");
console.log(dogs); // ["Alaskan Klee Kai", "Bull Terrier", "Pitbull"]
console.log(removedDogs); // ["American Bulldog"]

The code above I said .splice from index 1, remove index 1, insert 'Bull Terrier' so now the variable removedDogs contain the item removed from the index defined which in this case is 1.

Adding elements/values to an Array

So instead of use the length of an Array to add an element to the end or even harder to add an element to the beginning of an Array which you would have to iterate through the Array and shift the index from the end towards start. Anyway. Let's keep it simple with these two methods to add new elements to an Array Array.prototype.push() add to the end of an Array and Array.prototype.unshift() add to the beginning of an Array (Both methods accept multiple values/elements passed as arguments).

The push() function/method add a value/element to the end of an Array.
Here's an example.

var dogs = ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];
console.log(dogs); // ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];

dogs.push('Bull Terrier');
console.log(dogs); // ["Alaskan Klee Kai", "American Bulldog", "Pitbull", "Bull Terrier"]

The unshift() function/method add a value/element to the beginning of an Array.
Here's an example.

var dogs = ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];
console.log(dogs); // ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];

dogs.unshift('American Bulldog');
console.log(dogs); // ["American Bulldog", "Alaskan Klee Kai", "American Bulldog", "Pitbull"]

Removing elements/values from an Array

There's also two methods to remove values/elements from an Array where you can remove the beginning using Array.prototype.shift() or if you want to remove from the end you can use Array.prototype.pop().

Here's an example to remove the first element using the Array.prototype.shift() method.

var dogs = ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];
console.log(dogs); // ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];

dogs.shift();
console.log(dogs); // [ 'American Bulldog', 'Pitbull'];

And here's an example to remove the last element using the Array.prototype.pop() method.

var dogs = ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];
console.log(dogs); // ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];

dogs.pop();
console.log(dogs); // ['Alaskan Klee Kai', 'American Bulldog'];

Ordering/Sorting elements

There's also two ways to order/sort an Array Array.prototype.reverse() which are going to do what says and Array.prototype.sort() to put elements in order but in this case the method Array.prototype.sort() turns every value in strings so if you have numbers you are going to need to pass a function and order the numbers.

Here's an example of Array.prototype.reverse().

var dogs = ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];
console.log(dogs); // ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];

dogs.reverse();
console.log(dogs); // ["Pitbull", "American Bulldog", "Alaskan Klee Kai"];

Here's an example of Array.prototype.sort() with strings.

var alphabet = ['a', 'b', 'e', 'z', 'f', 'c'];
console.log(alphabet); // ['a', 'b', 'e', 'z', 'f', 'c']

alphabet.sort();
console.log(alphabet); // ["a", "b", "c", "e", "f", "z"]

And here's an example of how to pass a function to Array.prototype.sort() to order numbers.

var nums = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
console.log(nums) // [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

nums.sort(function(n1, n2) {
  return n1 - n2;
});

console.log(nums) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Iterator methods

The iterator methods/functions are going to be applied for each value/element and may or may not return a new array, groups of values or just a value as result of the operation.

First let's talk about the Array.prototype.forEach() which receive a callback as argument and this callback has three arguments respectively element, index, array being traversed going to iterate on ascending order.
Here's an example using Array.prototype.forEach().

var dogs = ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];

dogs.forEach(function(value, index, array) {
    console.log('Dog breed: ' + value + ', position: ' + index);
});

// outputs
// Dog breed: Alaskan Klee Kai, position: 0
// Dog breed: American Bulldog, position: 1
// Dog breed: Pitbull, position: 2 

Now it's time to show the Array.prototype.every() which test a condition against each element and return true in case all elements meet the condition or false.
Also receives a callback as argument and this callback has three arguments respectively element, index, array being traversed.

var nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

var meetCondition = nums.every(function(element, index, array) {
    return (element < 11);
});

console.log(meetCondition) // true

In the code above all elements are tested against the condition to check if they are less than 11 in our case all elements are less than 11 so the result returned is true.

The method/function Array.prototype.some() works almost the same way as Array.prototype.every() but in this case if at least one element meet the condition would return true.

var nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

var meetCondition = nums.some(function(element, index, array) {
    return (element === 11);
});

console.log(meetCondition) // true

The Array.prototype.reduce() method run a function against an accumulator for each element until reduce to one single value.

var nums = [100, 200, 300, 400];

nums.reduce(function(a, b) {
    console.log('a', a);
       console.log('b', b);
       console.log('result accumulated is: ', a + b);
    return a + b;
});

// output

// a 100
// b 200
// result accumulated is: 300
// a 300
// b 300
// result accumulated is: 600
// a 600
// b 400
// result accumulated is: 1000

As you can see our method Array.prototype.reduce() receive a function with two arguments previous value and current value a + b which the result turns into the accumulator a and then calculate this result against the next in line which is b and so on so forth.
You can also pass initial value where it's going to turn into the previous value and the original previous value turn into current value.

var nums = [100, 200, 300, 400];

nums.reduce(function(a, b) {
    console.log('a', a);
       console.log('b', b);
       console.log('result accumulated is: ', a + b);
    return a + b;
}, 200);

// output

// a 200
// b 100
// result accumulated is: 300
// a 300
// b 200
// result accumulated is: 500
// a 500
// b 300
// result accumulated is: 800
// a 800
// b 400
// result accumulated is: 1200
// 1200

There's also the possibility to use Array.prototype.reduceRight() which is going to perform the function on each element of the array from the end to start.

the Array.prototype.map() method works the same way Array.prototype.forEach() method works but return a new Array as the difference between the two methods.

var dogs = ['Alaskan Klee Kai', 'American Bulldog', 'Pitbull'];

var newArr = dogs.map(function(value, index, array) {
    console.log('Dog breed: ' + value + ', position: ' + index);
    return value;
});

console.log(newArr);

// outputs
// Dog breed: Alaskan Klee Kai, position: 0
// Dog breed: American Bulldog, position: 1
// Dog breed: Pitbull, position: 2 

// ["Alaskan Klee Kai", "American Bulldog", "Pitbull"]

The Array.prototype.filter() method works almost the same way as Array.prototype.every() but instead return an Array with the elements that met the condition true.

var nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

var numsLessThan5 = nums.filter(function(element, index, array) {
    return (element < 5);
});

console.log(numsLessThan5) // [0, 1, 2, 3, 4] 

That's it

I hope you have brush up on your Array knowledge being aware of we can use and will use more complex approaches applying some of the topics I covered on this post.

Cheers!

* Don't be shy. I will appreciate any improvement and/or fix.


More Stories

Cover Image for Using ChatGPT as your nutritionist

Using ChatGPT as your nutritionist

While ChatGPT is primarily known for its conversational abilities, it can also serve as a virtual trainer and nutritionist, providing personalized guidance to help you achieve your health and wellness goals.

Cover Image for How to invest in the stock market - a beginners guide

How to invest in the stock market - a beginners guide

There is so much bad information on how to invest in stock market causing a lot of confusion for people that want to get started in investing that I decided to create a guideline for beginners based on Peter Lynch work