Array

  1. Methods pop and push
  2. Methods shift/unshift
  3. Iterating over array
    1. join and split
  4. Using length to trim an array
  5. Array is Object, consequences.
  6. Sparse arrays, details of length
  7. Removing from an array
    1. Method splice
    2. Method slice
  8. Method reverse
  9. Sorting, method sort(fn)
  10. More on array definition
    1. new Array()
    2. Multidimensional arrays
  11. Summary

Here we’ll talk about regular arrays, that is with numeric indices.

An array is usually declared using square-bracketed notation:

var fruits = ["Apple", "Orange", "Donkey"]

To get an element, put its index in square brackets. First index is 0:

var fruits = ["Apple", "Orange", "Donkey"]

alert(fruits[0])
alert(fruits[1])
alert(fruits[2])

We can also retrieve its length:

var fruits = ["Apple", "Orange", "Donkey"]

alert(fruits.length)

Wops! We created an array with two fruits and a donkey. The next step will be to remove the donkey.

Methods pop and push

There is a method pop which removes last item and returns it.

The following example demonstrates how the “Donkey” is being popped out.

var fruits = ["Apple", "Orange", "Donkey"]

alert("I remove "+fruits.pop())

// Now we have ["Apple","Orange"]

alert("Now length is: "+fruits.length) // donkey removed

Note how pop modifies the array itself.

A counterpart to pop is push which appends an element to the array. Let’s say we’ve forgotten a peach:

var fruits = ["Apple", "Orange"]

fruits.push("Peach");

// now got ["Apple", "Orange", "Peach"]

alert("Last element is:"+fruits[fruits.length-1])

  1. Create an array styles with elements “Jazz”, “Blues”.
  2. Append a value “Rock’n’Roll”
  3. Replace the second value from tail by “Classic”. The array should become “Jazz”,”Classic”,”Rock’n’Roll”. The code should work for any array length.
  4. Extract the last value from the array and alert it.
Open solution
Solution

// 1
var styles = ["Jazz", "Bluez"]

// 2
styles.push("Rock'n'Roll") // or: styles[styles.length] = "Rock'n'Roll"

// 3 
styles[styles.length-2] = "Classic"

// 4
alert( styles.pop() )

Methods shift/unshift

Methods pop/push manipulate with the end of array, but you can also use shift to shift off first value or unshift to prepend a value to an array.

var fruits = ["Apple", "Orange"]

var apple = fruits.shift() // now we have only ["Orange"] left

fruits.unshift("Lemon") // now got ["Lemon", "Orange"]

alert(fruits.length) // 2

Both push and unshift can add multiple elements at once:

var fruits = ["Apple"]

fruits.push("Orange","Peach")
fruits.unshift("Pineapple","Lemon")

// now: ["Pineapple", "Lemon", "Apple", "Orange", "Peach"]

Write a code to alert a random value from array arr:

var arr = ["Plum","Orange","Donkey","Carrot","JavaScript"]

P.S. The code to get a random integer from min to max (inclusive) is:

var rand = min + Math.floor(Math.random()*(max+1-min))

Open solution
Solution

We need to get a random integer from 0 to arr.length-1(inclusive).

var arr = ["Plum","Orange","Donkey","Carrot","JavaScript"]

var rand = Math.floor(Math.random()*arr.length)

alert(arr[rand])

Iterating over array

To iterate over elements, a loop over all indices is usually used.

The following example demonstrates iterating with for loop.

var fruits = ["Pineapple", "Lemon", "Apple", "Orange", "Peach"]

for(var i=0; i<fruits.length; i++) {
  alert(fruits[i])
}

Create a function find(arr,value) which finds a value in given array and returns its index, or -1 if not found.

For instance:

arr = [ "test", 2, 1.5, false ]

find(arr, "test") // 0
find(arr, 2) // 1
find(arr, 1.5) // 2

find(arr, 0) // -1

Open solution
Solution

A possible solution could look like that:

function find(array, value) {

  for(var i=0; i<array.length; i++) {
    if (array[i] == value) return i;
  }
   
  return -1;
}

Although it is wrong, because == makes no difference between 0 and false.

More correct variant uses ===. Also, there is a native function Array#indexOf in the newer ES5 standard. So we can define the function like this:

function find(array, value) {
  if (array.indexOf) return array.indexOf(value) 

  for(var i=0; i<array.length; i++) {
    if (array[i] === value) return i;
  }
   
  return -1;
}

var arr = ["a", -1, 2, "b"];

var index = find(arr, 2);

alert(index);

An even smarter step would be to define find conditionally, by checking if the indexOf method exists. We’ll cover that in the next sections.

Create a function filterNumeric(arr) which takes an array and returns new array which contains only numeric values from arr.

An example of how it should work:

arr = ["a", 1, "b", 2];

arr = filterNumeric(arr);
// now arr = [1,2]

Open solution
Solution

The solution is to iterate over array and add a value to new array only if it is numeric. Check it out here.

join and split

Sometimes we need a quick’n’easy way to turn an array into a string. That is exactly what join method is for.

It joins an array into string using given separator:

var fruits = ["Lemon","Apple","Orange","Peach"];

var str = fruits.join(', ');

alert(str);

The inverse operation is also easy with split:

var fruits = "Apple,Orange,Peach";

var arr = fruits.split(',');

// arr is ["Apple", "Orange", "Peach"]

alert(arr[0]);

An object has a className property which keeps it’s class names delimited by spaces:

var obj = {
  className: 'open menu'
}

Write a function addClass(obj, cls) which adds a class cls, but only if it doesn’t yet exist:

addClass(obj, 'new') // obj.className='open menu new'
addClass(obj, 'open')  // no changes (class already exists)
addClass(obj, 'me') // obj.className='open menu new me'

alert(obj.className)  // "open menu new me"

P.S. Your function shouldn’t add extra spaces.

Open solution
Solution

The solution is to split the className and loop over pieces. If there is no matching class, then add it.

The loop is slightly optimized for performance:

function addClass(elem, cls) {
  for(var c = elem.className.split(' '), i=c.length-1; i>=0; i--) {
    if (c[i] == cls) return
  }
	
  elem.className += ' '+cls
}

var obj = { className: 'open menu' }

addClass(obj, 'new')
addClass(obj, 'open') 
alert(obj.className)   // open menu new

In the example above, var c is defined in the beginning of the loop and i is set to it’s last index.

The loop itself goes backwards, ending condition is i>=0. The reason is that i>=0 check is faster than i. It evades length property lookup in c.


Create a function camelize(str) which transforms a string from “my-short-string” to “myShortString”.

So, all parts after a hyphen become camelcased instead. For instance:

camelize("background-color") == 'backgroundColor'
camelize("list-style-image") == 'listStyleImage'

Such function may be useful when operating with CSS.

Note. Remember charAt, substr and check str.toUpperCase() function which transforms the string to upper case.

Open solution
Solution

There is a number of ways to implement such task.

A possible solution is here.

Using length to trim an array

Using length property, one can trim an array as follows:

var arr = [0, 1, 2, 3] 

alert(arr[2]); // ok it's here

arr.length = 2; // trim to 2 elements (that is: [0,1])

alert(arr[2]); // nope, it was trimmed out

You just set the length and browser trims the array.

Array is Object, consequences.

In fact Array in JavaScript is internally an Object extended with auto-length and special methods.

This is different from arrays in some languages which represent a contiguous segment of memory, and also different from queue/stack structures based on linked-lists.

Non-numeric array keys

The keys are numeric, but can have any name:

arr = []
arr[0] = 5
*!*arr.prop = 10*/!* // don't do that

Although that’s not recommended. Numeric arrays are suited for numeric keys, objects are for associative key-value pairs. There’s usually no reason to mix them.

In JavaScript, arrays being a hash table gives certain performance benefits and drawbacks.

For instance, push/pop operate on last element of array only, so they are blazingly fast, say O(1).

See what I mean, push only works with the tail:

var arr = ["My", "array"]
arr.push("something")

alert(arr[1]) // string "array"

Methods shift/unshift are slow, because they have to renumber whole array. Method splice may also lead to renumbering.

So, using shift/unshift is generally slower than push/pop. The larger array - the more work to renumber it.

What will be the result? Why?

arr = ["a", "b"]

arr.push( function() { alert(this) } )

arr[arr.length-1]()  // ?

Open solution
Solution

Because arrays are objects, arr<a href="/..">..</a> is actually an object method call, like obj<a href="/method">method</a>.

arr[arr.length-1]() 

// is same as
arr[2]()

// syntactically wrong, but ideologically same as:
arr.2() 

// rewritten to be same style as obj.method()

this = arr is passed to the function in such case, so the contents of arr is alerted.

arr = ["a", "b"]

arr.push( function() { alert(this) } )

arr[arr.length-1]() // "a","b",function

Sparse arrays, details of length

The length property in JavaScript is not quite a length, it is last index + 1.

That becomes important in sparse arrays, with ‘holes’ in indexes.

In the next example we add two elements to empty fruits, but length becomes 100:

var fruits = [] // empty array

fruits[1] = 'Peach'
fruits[99] = 'Apple'

alert(fruits.length)  // 100 (but 2 elements)

If you try to output a sparse array, the browser outputs values at skipped indexes as empty:

var fruits = [] // empty array

fruits[2] = 'Peach'
fruits[5] = 'Apple'

alert(fruits)  // ,Peach,,,Apple (or kind of)

But naturally, an array is just an object with two keys. The missing values do not occupy space.

Sparse arrays behave weird when array methods are applied to them. They don’t have an idea that indexes are skipped:

var fruits = [ ]

fruits[1] = 'Peach'
fruits[9] = 'Apple'

alert( fruits.pop() ) // pop 'Apple' (at index 9)
alert( fruits.pop() )  // pop undefined (at index 8)

Try to evade sparse arrays. Anyway, it’s methods won’t work well. Use an Object instead.

Removing from an array

As we know, arrays are just objects. So we could use delete to remove a value:

var arr = ["Go", "to", "home"]

delete arr[1]

// now arr = ["Go", undefined, "home"]
alert(arr[1]) // undefined

You see, the value is removed, but probably not the way we’d want it to be, because array has got an undefined hole inside.

A delete operator removes key-value pair, that’s all it does. Naturally, because array is just a hash, the slot becomes undefined.

More often we need to remove an item without leaving holes between indexes. There is another method which helps with that.

Method splice

Method splice is a swiss-knife for JavaScript arrays, it can delete elements and replace them.

It’s syntax is as follows:

arr.splice(index, deleteCount[, elem1, ..., elemN])
Remove deleteCount elements starting with index and then paste elem1, ..., elemN on their place.

Let’s see a few examples.

var arr = ["Go", "to", "home"]

arr.splice(1, 1)  // remove 1 element starting at index 1

alert( arr.join(',') ) // ["Go", "home"] (1 element removed)

This way you can use splice to remove a single element from an array. Array numbers shift to fill the gap.

var arr = ["Go", "to", "home"]

arr.splice(0, 1)  // remove 1 element starting at index 0

alert( arr[0] ) // "to" became first element

The next example demonstrates how to replace elements.

var arr = [*!*"Go", "to", "home",*/!* "now"];

// remove 3 first elements and add two
arr.splice(0, 3, "Come", "here") 

alert( arr ) // [*!*"Come", "here"*/!*, "now"]

Method splice returns array of removed elements:

var arr = [*!*"Go", "to", "home",*/!* "now"];

// remove 2 first elements 
var removed = arr.splice(0, 2) 

alert( removed ) // "Go", "to" <-- array of removed elements

Splice is able to insert elements, just set deleteCount to 0.

var arr = ["Go", "to", "home"];

// from 2nd position 
// delete 0 
// and insert "my", "sweet"
arr.splice(2, 0, "my", "sweet") 

alert( arr) // "Go", "to", "my", "sweet", "home"

It also can use a negative index, which counts from array end:

var arr = [1, 2, 5]

// at element -1 (pre-last)
// delete 0 elements, 
// then insert 3 and 4
arr.splice(-1, 0, 3, 4)

alert(arr)  // 1,2,3,4,5

An object has a className property which keeps it’s class names delimited by spaces:

var obj = { 
  className: 'open menu'
}

Write a function removeClass(obj, cls) which removes a class cls if it is set:

removeClass(obj, 'open') // obj.className='menu'
removeClass(obj, 'blabla')  // no changes (no class to remove)

Open solution
Solution

The solution is to split the className and loop over pieces. If there is a match, then remove it from the array and join the array back at the end.

We’ll do it in a slightly optimized way:

function removeClass(elem, cls) {
  for(var c = elem.className.split(' '), i=c.length-1; i>=0; i--) {
    if (c[i] == cls) c.splice(i,1)
  }
	
  elem.className = c.join(' ')
}

var obj = { className: 'open menu' }

removeClass(obj, 'open')
removeClass(obj, 'blabla')
alert(obj.className)   // menu

In the example above, var c is defined in the beginning of the loop and i is set to it’s last index.

The loop itself goes backwards, ending condition is i>=0. The reason is that i>=0 check is faster than i. It evades length property lookup in c.

Create a function filterNumericInPlace(arr) which takes an array and removes all non-numeric values from it.

An example of how it should work:

arr = ["a", 1, "b", 2];

filterNumericInPlace(arr);

alert(arr)  // [1,2]

Open solution
Solution

The solution is to iterate over array and use arr.splice to remove non-numeric values. Check it out here.

Method slice

You can also extract a portion of array using slice(begin[, end]):

var arr = ["Why", "learn", "JavaScript"];

var arr2 = arr.slice(0,2) // take 2 elements starting at 0

alert(arr2.join(', ')) // "Why, learn"

Note, this method does not modify array, it just copies a slice of it.

You can omit second argument to get all elements starting with certain index:

var arr = ["Why", "learn", "JavaScript"];

var arr2 = arr.slice(1) // take all elements starting at 1

alert(arr2.join(', ')) // "learn, JavaScript"

The method also supports negative indices, just like String#slice.

Method reverse

Another useful method is reverse. Suppose, I want a last part of a domain, like “com” from “my.site.com”. Here is how I can do that:

var domain = "my.site.com"

var last = domain.split('.').reverse()[0]

alert(last)

Note how JavaScript allows complex syntax like: reverse()[0] - to call a method and then take an element of resulting array.

Actually, you can compose longer calls, like reverse()<a href="/0%5D%5B1">0][1</a>[5]..., language syntax allows that.

Sorting, method sort(fn)

Method sort() sorts the array in-place:

var arr = [ 1, 2, 15 ]

arr.sort()

alert( arr )   // 1, 15, 2

Run the example above. Notice something strange? The order is 1, 15, 2.

That’s because sort converts everything to string and uses lexicographical order by default.

To make it smarter, we need to pass in the custom comparison function. It should accept two arguments and return 1, 0 or -1:

function compare(a, b) {
  if (a > b) return 1
  else if (a < b) return -1
  else return 0
}

var arr = [ 1, 2, 15 ]

arr.sort(compare)

alert( arr )   // 1, 2, 15

Now it works right.

Create a function ageSort(people) to sort array of people objects by their age.

var john = { name: "John Smith", age: 23 }
var mary = { name: "Mary Key", age: 18 }
var bob = { name: "Bob-small", age: 6 }

var people = [ john, mary, bob ]

ageSort(people) // now people is [ bob, mary, john ]

Output people names after sorting.

Open solution
Solution

The solution makes use of Array#sort and custom comparison:

function ageCompare(a, b) {
  if (a.age > b.age) return 1
  else if (a.age < b.age) return -1
  return 0
}

*!*
function ageSort(people) {
  people.sort(ageCompare)
}
*/!*

// test it
var john = { name: "John Smith", age: 23 }
var mary = { name: "Mary Key", age: 18 }
var bob = { name: "Bob-small", age: 6 }

var people = [ john, mary, bob ]

ageSort(people)

// check the order
for(var i=0; i<people.length; i++) {
  alert(people[i].name)
}

Shorter variant

The comparison function may be shorter. Alternative solution:

people.sort(function(a,b) { return a.age - b.age })

It works, because it is not required to return 1/-1/0, positive or negative will do.

More on array definition

new Array()

Technically, there is another syntax to define an array:

var arr = Array("Apple", "Peach", "etc")

It is rarely used, just because square brackets [] are shorter.
Also, there is a pitfall here, because new Array, called with single numeric argument produces an array of undefined with given length:

var arr = new Array(2,3) // ok we have [2, 3]

arr = new Array(2) // do we have [2] ?

alert(arr[0]) // no! we have array [undefined, undefined]

The example above outputs undefined, because new Array(number) creates an empty array with length set to number.

That might be quite unexpectable. But if you know about the feature, then here’s a nice use of new Array(number):

var indent = new Array(5).join('a') // aaaa (4 times)

That’s a smart way to repeat a string.

Multidimensional arrays

Arrays in JavaScript can store any data type inside.

var arr = ["My", "Small array", true, {name:'John'}, 345]
alert(arr[1]) // Small array

That can be used to store multidimensional arrays:

var matrix = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]

alert(matrix[1][1]) // central element

Make a generic function filter(arr, func) which filters an array using given function.
Only those elements for which func(elem) returns true should compose the result.

Every element which pass through and returns new array which contains only numeric values from arr.

An example of how it should work:

arr = ["a", -1, 2, "b"]

arr = filter(arr, isNumeric)
// arr = [-1, 2], only numeric in result

arr = filter(arr, function(val) { return val > 0 })
// arr = [2] , for other values function returns false

Open solution
Solution

There is nothing really special in this task. Passing functions around and applying them is easy in JavaScript. Check the solution here.

A prime number is a natural number which has exactly two distinct natural number divisors: 1 and itself.

To find all the prime numbers less than or equal to a given integer n by Eratosthenes’ Sieve:

  1. Create a list of consecutive integers from two to n: (2, 3, 4, ..., n).
  2. Set p=2, the first prime number.
  3. Strike from the list all multiples of p less than or equal to n. (2p, 3p, 4p, etc.)
  4. Set p to first not striked number in the list after p.
  5. Repeat steps 3-4 until p*p > n.
  6. All the remaining numbers in the list are prime.

There is also an animation available.

Implement the Eratosthenes’ Sieve in JavaScript. Compute the sum of all primes up to 100 and alert it.

Open solution
Solution

The answer is 1060.

The solution is at tutorial/intro/array/sieve.html.

Summary

That’s all with deep introduction to array.

We’ve covered:

  1. How to declare an array, two syntaxes.
  2. How to add, replace, remove from/to array and its both ends.
  3. How to iterate over an array.
  4. How to split a string into array and join it back.
  5. Relations between Array and Object in JavaScript

That’s enough 95% of time. For more methods and examples, refer to Array in Mozilla manual.

See also:

Tutorial

Donate

Donate to this project