# Array

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"]

```

We can also retrieve its length:

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

```

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"]

// 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"]

```

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
```

## 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"]

```

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)

```

## 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++) {
}
```

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);

```

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(', ');

```

The inverse operation is also easy with `split`:

```var fruits = "Apple,Orange,Peach";

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

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

```

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

```var obj = {
}
```

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'

```

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' }

```

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]

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")

```

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"]
```

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)

```

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

```var obj = {
}
```

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')
```

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);

```

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

```

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

```

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]

```

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++) {
}
```

## 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]
```

That can be used to store multidimensional arrays:

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

```

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 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.