This article illustrates the operations of JavaScript Array. These examples include built-in APIs and some custom functions, such as groupBy, union, objectToArray, etc.
Note if fruits
is not initialized in examples, it is:
let fruits = ['Apple', 'Banana'];
Basic operations
Create
let fruits = ['Apple', 'Banana'];
let length = fruits.length;
// 2
let fruits1 = [];
fruits1.push('Apple'); // ['Apple']
fruits1.push('Banada');// ['Apple', 'Banana'];
let fruits2 = new Array('Apple', 'Banana');
// Creates an array of 2 empty slots, not slots with actual undefined values
let fruit3 = new Array(2);
console.log(fruits3);
// Array [undefined, undefined]
Create an two-dimensional array
let board = [
['A0','A1','A2'],
['B0','B1','B2'],
['C0','C1','C2']
];
Set values
Set values directly
let fruits = ['Apple', 'Banana'];
fruits[1] = 'Blackberry';
If you set a value at a new indexed position which is not contained in the array. The length of the array will be updated accordingly.
let fruits = ['Apple', 'Banana'];
fruits[4] = 'Damson';
console.log(fruits); // ['Apple', 'Banana', undefined, undefined, 'Damson'];
console.log(furits.length); // 5
console.log(Object.keys(fruits)); // ['0', '1', '4']
**Fill values **
The fill()
method fills (modifies) all the elements of an array from a start index (default zero) to an end
index (default array length) with a static value. It returns the modified array.
Syntax: fill(value[, start[, end]])
let array1 = [1, 2, 3, 4];
// fill with 0 from position 2 until position 4
console.log(array1.fill(0, 2, 4));
// expected output: [1, 2, 0, 0]
// fill with 5 from position 1
console.log(array1.fill(5, 1));
// expected output: [1, 5, 5, 5]
console.log(array1.fill(6));
// expected output: [6, 6, 6, 6]
Access
length
console.log(fruits.length);
[] operator
Access an element through index
let first = fruits[0];
// Apple
let last = fruits[fruits.length - 1];
// Banana
Note: It is possible to quote the array indexes, such as
fruits['0']
, although it is not necessary. The 0 infruits[0]
is coerced into a string by the JavaScript engine through an implicittoString
conversion.
Add, change
push() – Add to the end
// push() changes the length and returns the new length
let newLength = fruits.push('Coconut'); // ["Apple", "Banana", "Coconut"]
// 3
unshift() – Add to the front
// unshift() changes the length and returns the new length
let newLength = fruits.unshift('Avocado');// ["Avocado", "Apple", "Banana"];
// 3
[] operator – Add by setting a value at a new index position
let fruits = ['Apple', 'Banana'];
fruits[4] = 'Damson';
console.log(fruits); // ['Apple', 'Banana', undefined, undefined, 'Damson'];
console.log(furits.length); // 5
console.log(Object.keys(fruits)); // ['0', '1', '4']
When setting a property on a JavaScript array when the property is an valid array index and that index is outside the current bounds of the array, the engine will update the array’s length
property accordingly.
splice() – Add value of a specific position
The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place. It returns an array containing the deleted elements.
let arrDeletedItems = arr.splice(start[, deleteCount[, item1[, item2[, ...]]]])
- start
The index at which to start changing the array.
-
deleteCount
The number of elements in the array to remove from
start
. -
item1, item2, ...
The elements to add to the array, beginning from
start
. If you do not specify any elements,splice()
will only remove elements from the array.
Example
let fruits = ['Apple', 'Banada', 'Coconut'];
// Remove 0 item from index of 1, and adding new item 'Blueberry'
let deletedItems = fruits.splice(1, 0, 'Blueberry'); // Add at index
// deletedItems: []
// fruits: ['Apple', 'Blueberry', Banada', 'Coconut']
Delete, remove
Delete from the end of an array
The pop() method removes the last element from an array and returns that element. This method changes the length of the array.
It returns undefined
if the array is empty.
// pop() returns the removed element, it changes the length
// remove Banada from the end
let last = fruits.pop(); // ["Apple"];
// Banada
Delete from the front of an array
// shift() returns the removed element, it changes the length
// remove Apple from the front
let first = fruits.shift(); // ["Banana"];
// Apple
Delete elements from any position of an array
The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place. It can be used to remove elements from any position.
let fruits = ['Apple', 'Banada', 'Coconut', 'Durian'];
// Delete fruits[1] and fruits[2]
let removed = fruits.splice(1, 2); // fruits: ['Apple', 'Durian']
console.log(removed); // ['Banada', 'Coconut']
Loop
There are several ways to loop over an array. Use map
、reduce
、filter
functions first if they satisfy your needs, otherwise use below loop operations. Although these function are slower, they are easier to code、read , maintain and test. See for vs for each vs (map, reduce, filter, find) for details.
Use for loop
for (let i = 0; i < furits.length; ++i) {
console.log(furits[i]);
}
Use forEach method
The forEach()
method executes a provided callback function once for each array element.
// The parameters of index and array are optional
fruits.forEach(function(currenValue, index, array) {
console.log(curentValue, index);
});
// "Apple" 0
// "Banada" 1
Note: It is not invoked for index properties that have been deleted or are uninitialized. For example:
“`javascript
const arraySparse = [1,3,,7];
let numCallbackRuns = 0;arraySparse.forEach(function (element) {
console.log(element);
numCallbackRuns++;
});
console.log(arraySparse); // 3
“`
Formatted print
Use console.table
console.table
displays tabular data as a table. This feature is available in Web Workers.
console.table(['Apple', 'Banada']);
console.table(board); // prints a two-demensional array
Write your own function
function printArrayElements(element, index, array) {
console.log('a[' + index + '] = ' + element);
}
fruits.forEach(printArrayElements);
// a[0] = "Apple"
// a[1] = "Banada"
Other Operations
Copy
Copy to a new array
The slice(begin, end)
method returns a shallow copy of a portion of an array into a new array object (end
not included) . The original array will not be modified.
let fruits = ['Apple', 'Banada'];
let shallowCopy = fruits.slice(); // this is how to make a copy
// ["Apple", "Banada"]
Syntax: slice([begin[, end]])
.
Copy elements to the same array
The copyWithin(target, start, end)
method shallow copies part of an array to target location in the same array and returns it without modifying its length.
Syntax: copyWithin(target[, start[, end]])
.
let array1 = ['a', 'b', 'c', 'd', 'e'];
// copy to index 0 the element at index 3
console.log(array1.copyWithin(0, 3, 4));
// expected output: Array ["d", "b", "c", "d", "e"]
// copy to index 1 all elements from index 3 to the end
console.log(array1.copyWithin(1, 3));
// expected output: Array ["d", "d", "e", "d", "e"]
Filter
The filter()
method creates a new array with all elements that pass the test implemented by the provided function.
let fruits = ['Apple', 'Banana', 'Blueberry'];
let bfruits = fruits.filter(val => val.startsWith('B'));
// ['Banana', 'Blueberray']
Find
findIndex()
The findIndex()
method returns the index of the first element in the array that satisfies the provided testing function.
Syntax
arr.findIndex(callback( element[, index[, array]] )[, thisArg])
Parameters
- callback
A function to execute on each value in the array until the function returns
true
, indicating that the satisfying element was found.It takes three arguments:
element
The current element being processed in the array.
index
Optional
The index of the current element being processed in the array.
array
Optional
The array
findIndex()
was called upon. -
thisArg
OptionalOptional object to use as
this
when executingcallback
.
Examples
let furits = ['Apple', 'Banana'];
function startsWithB(element) {
return element.startsWith('B');
}
console.log(fruits.findIndex(startsWithB));
// expected output: 1
find()
The find()
method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined
is returned.
let array1 = [5, 12, 8, 130, 44];
let elemnent = array1.find(function(element) {
return element > 10;
});
console.log(element);
// 12
indexOf()
Get index of an element
The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.
Syntax
arr.indexOf(searchElement[, fromIndex])
Parameters
- searchElement
Element to locate in the array.
-
fromIndex
OptionalThe index to start the search at. If the index is greater than or equal to the array’s length, -1 is returned, which means the array will not be searched. If the provided index value is a negative number, it is taken as the offset from the end of the array. Note: if the provided index is negative, the array is still searched from front to back. If the provided index is 0, then the whole array will be searched. Default: 0 (entire array is searched).
indexOf()
compares searchElement
to elements of the Array using strict equality (the same method used by the ===
or triple-equals operator).
Examples
let array = [2, 9, 9];
array.indexOf(2); // 0
array.indexOf(7); // -1
array.indexOf(9, 2); // 2
array.indexOf(2, -1); // -1
array.indexOf(2, -3); // 0
includes()
Check whether an array includes a certain value
The includes()
method determines whether an array includes a certain value among its entries, returning true
or false
as appropriate.
Syntax: includes(valueToFind[, fromIndex])
let fruits = ['Apple', 'Banana'];
console.log(fruits.includes('Orange'));// false
console.log(fruits.includes('App'));// false
Note: When comparing strings and characters,
includes()
is case-sensitive.Note: Technically speaking,
includes()
uses thesameValueZero
algorithm to determine whether the given element is found.
Join
The join(sperator)
method creates and returns a new string by concatenating all of the elements in an array (or an array-like object), separated by commas or a specified separator string
let fruits = ['Apple', 'Banada'];
console.log(fruits.join());
// expected output: "Apple,Banada"
console.log(elements.join('-'));
// expected output: "Apple-Banada"
let board = [
['A','B','C'],
['D','E','F'],
['G','H','I']
];
console.log(board.join('n'));
// Output:
/*
A,B,C
D,E,F
G,H,I
*/
Merge / Concat
The concat()
method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.
let array1 = ['a', 'b', 'c'];
let array2 = ['d', 'e', 'f'];
console.log(array1.concat(array2));
// Array ["a", "b", "c", "d", "e", "f"]
Sort
Reverse
The reverse()
method reverses an array in place. The first array element becomes the last, and the last array element becomes the first.
let array1 = ['one', 'two', 'three'];
let reversed = array1.reverse();
console.log(array1); // Array ['three', 'two', 'one']
console.log(reversed); // Array ['three', 'two', 'one']
Check/Test
Every: Test whether all elements pass provided function
The every()
method tests whether all elements in the array pass the test implemented by the provided function.
function isBelowThreshold(currentValue) {
return currentValue < 40;
}
let array1 = [1, 30, 39, 29, 10, 13];
console.log(array1.every(isBelowThreshold));
// true
Note: This method returns
true
for any condition put on an empty array.
Some: Test whether at least some elements pass provided function
The some()
method tests whether at least one element in the array passes the test implemented by the provided function.
let even = function(element) {
// checks whether an element is even
return element % 2 === 0;
};
let array = [1, 2, 3, 4, 5];
console.log(array.some(even));
// true
Note: This method returns
false
for any condition put on an empty array.
isArray
The Array.isArray()
method determines whether the passed value is an Array
.
Array.isArray([1, 2, 3]); // true
Array.isArray({foo: 123}); // false
Array.isArray('foobar'); // false
Array.isArray(undefined); // false
isArray vs instance of
When checking for
Array
instance,Array.isArray
is preferred overinstanceof
because it works throughiframes
.
String to Array, Map to Array, Set to Array
(Array.from('foo'));
// ['f', 'o', 'o']
The Array.from()
method creates a new, shallow-copied Array
instance from an array-like or iterable object.
Array.from()
lets you create Array
s from:
- array-like objects (objects with a
length
property and indexed elements) or - iterable objects (objects where you can get its elements, such as
Map
andSet
)
const set = new Set(['foo', 'bar', 'baz', 'foo']);
Array.from(set);
// ['foo', 'bar', 'baz']
Other loops: map vs reduce
map
map() method creates a new array with the results of calling a provided function on every element in the calling array.
Syntax:
let new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg]
- currentValue, the current value in the array
- index
- array, the array itself
- thisArg, Value to use as
this
when executingcallback
.
Examples:
[1, 4, 9].map((val) => {
return val * 2;
});
// It creates a new array: [2, 8, 18]
reduce
The reduce()
method executes a callback on each element of the array, resulting in a single output value.
Syntax:
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
- accumulator
The accumulator accumulates the callback’s return values. It is the accumulated value previously returned in the last invocation of the callback, or
initialValue
. -
currentValue, the current element being processed in the array.
-
index, the index of the current element being processed in the array.
-
array, the array reduce() was called upon.
-
initialValue
A value to use as the first argument to the first call of the
callback
. If noinitialValue
is supplied, the first element in the array will be used and skipped. Callingreduce()
on an empty array without aninitialValue
will throw aTypeError
.
Examples:
// Get sum of an array
[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array) {
return accumulator + currentValue;
});
Custom operations
Filter an Objects Array by fields
filter
is an object which defines the filter condition. If an object in the array has the properties with the same values in filter, it will be filtered out.
const filterArray = (arr, filter) => {
var data = [];
for (let obj of arr) {
let filtered = true;
for (let p in filter) { // for each property in filter
if (obj[p] != filter[p]) {
filtered = false;
break;
}
}
if (filtered) {
data.push(obj);
}
} // for
return data;
}
Examples:
let employees = [
{name: 'Jane', gender: 'Female'},
{name: 'Jim', gender: 'Male' },
{name: 'Lily', gender: 'Female'}
};
filterArray(employees, {gender: 'Female'});
// [{name: 'Jane', gender: 'Female'}, {name: 'Lily', gender: 'Female'}]
GroupBy
The following groupBy
groups objects in an array by a field.
const groupBy = (arr, field) => {
return arr.reduce(function (acc, obj) {
let key = obj[field];
acc[key] = acc[key] || [];
acc[key].push(obj);
return acc;
}, {});
}
Examples:
let employees = [
{name: 'Jane', gender: 'Female'},
{name: 'Jim', gender: 'Male' },
{name: 'Lily', gender: 'Female'}
];
groupBy(employees, 'gender');
// {
// 'Female': [{name: 'Jane', gender: 'Female'}, {name: 'Lily', gender: 'Female'}],
// 'Male': [{name: 'Jim', gender: 'Male' }]
// }
If you want an array of grouped objects:
const groupBy = (arr, field) => {
let groups = arr.reduce((acc, obj) => {
let key = obj[field];
acc[key] = acc[key] || [];
acc[key].push(obj);
return acc;
}, {});
return Object.keys(groups).map( group => {
return groups[group];
});
}
The result will be:
// [
// [{name: 'Jane', gender: 'Female'}, {name: 'Lily', gender: 'Female'}],
// [{name: 'Jim', gender: 'Male' }]
// ]
A more generic version
Below code (from javascript codesnipt) is a more generic version. It accepts an array of basic types or objects. It has 2 processes:
- Use map to generate a new array. Here
arr
is the array, andf
can be a function or a field name by which it is grouped. - Use reduce function to produce a object in which a field indicates a group.
const groupBy = (arr, f) =>
arr.map(typeof f === 'function' ? f : val => val[f]).reduce((acc, val, i) => {
acc[val] = (acc[val] || []).concat(arr[i]);
return acc;
}, {});
Examples:
groupBy([6.1, 4.2, 6.3], Math.floor); // {4: [4.2], 6: [6.1, 6.3]}
groupBy(['one', 'two', 'three'], 'length'); // {3: ['one', 'two'], 5: ['three']}
Of course it can be completed in one loop:
const groupBy = (arr, f) => {
return arr.reduce((acc, val) => {
let key = (typeof f === 'function') ? f(val) : val[f]).
acc[key] = acc[key] || [];
acc[key].push(val);
return acc;
}, {});
}
Union
Union operation returns each item in any of a and b once.
const union = (a, b) => Array.from(new Set([...a, ...b]));
Examples:
union([1, 2, 3], [4, 3, 2]);
// [1,2,3,4]
The union
above works only for primitive types. You can provides a comparison function to union other types.
const unionWith = (a, b, comp) =>
Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)]));
It filters the elements that does not appear in a from b, then makes a merge operation.
Array to Set
let set = new Set(['Apple', 'Banana', 'Apple']);
// ('Apple', 'Banana')
Unique Values in Array
const uniqueValues(arr) => [...new Set(arr)];
shuffle
The modern version implemented in JavaScript of this algorithm (Fisher-Yates Algorithm, from the book The Art of Computer Programming by Donald E. Knuth) goes like:
for(let i = array.length — 1; i > 0; i--){
const j = Math.floor(Math.random() * i)
const temp = array[i]
array[i] = array[j]
array[j] = temp
}
The Phaser’s shuffle method also uses this algorithm, the source code:
var Shuffle = function (array)
{
for (var i = array.length - 1; i > 0; i--)
{
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
Note
Below are two examples of when a random algorithm is not random enough:
- Flaw #1: An Off-by-One Error
random(n)
returns a number between 0 and (n-1), therefore it will never swap the 52nd card with itself; the 52nd card can never end up in the 52nd place.Flaw #2: The Shuffle Isn’t Uniform
It swaps the
i
th card with a random card selected from the entire deck. A proper algorithm will swap the ith card only with a card in the interval(i, n) so that each element for a random swap only once.Flaw #3: Using a 32-bit Seed
…
Flaw #4: Using the System Clock as a Seed
…
And words from Robert Sedgewick, author of Algorithms:
"That's a pretty tough thing to have happen if you're implementing online poker. You might want to make sure that if you're advertising that you're doing a random shuffle that you go ahead and do so."—Robert Sedgewick, Professor of Computer Science, Princeton
When Random Isn’t Random Enough: Lessons from an Online Poker Exploit
This example comes from a 1999 popular online poker platform implemented card-shuffling software. The algorithm used in the shuffling the 52 cards not random engouth:
{ Generate a new seed based on the system clock } randomize; { Randomly rearrange each card } for ctr := 1 to 52 do begin random_number := random(51)+1; tmp := card[random_number]; card[random_number] := card[ctr]; card[ctr] := tmp; end;
How To Correctly Shuffle An Array in JavaScript
Microsoft had this browser ballot screen on browserchoice.eu where Microsoft was supposed to show all the different browser choices to users in random order. Here is the code they used for doing the random shuffle:
array.sort(function (a, b) { return 0.5 — Math.random() })
But the algorithm was far from random. Here’s an interesting statistical analysis on the results of this algorithm.
More this sort function is also very inefficient, for it gives a very inconsistent ordering which could go into an infinite loop or stop after a few exchanges.
Object to Array
This operation convert an object to an array.
let objectToArray = obj => {
Object.keys(obj).map(val => {
return obj[val];
}
}
Use Array as object to store other properties
An array can be used as an object to store other properties.
let fruits = ['Orange', 'Lemon'];
fruits.kind = 'citrus';
Output an two-dimensional array in a table format
Use join()
let board = [
['A','B','C'],
['D','E','F'],
['G','H','I']
];
console.log(board.join('n'));
Output
A,B,C
D,E,F
G,H,I
Use console.table()
let board = [
['A','B','C'],
['D','E','F'],
['G','H','I']
];
console.log(board.join('n'));
Output
(index) | 0 | 1 | 2 |
---|---|---|---|
0 | “A” | “B” | “C” |
1 | “D” | “E” | “F” |
2 | “G” | “H” | “I” |