Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions 1-js/05-data-types/05-array-methods/10-average-age/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ importance: 4

# Get average age

Write the function `getAverageAge(users)` that gets an array of objects with property `age` and gets the average.
Write the function `getAverageAge(users)` that gets an array of objects with property `age` and returns the average age.

The formula for the average is `(age1 + age2 + ... + ageN) / N`.

Expand All @@ -19,4 +19,3 @@ let arr = [ john, pete, mary ];

alert( getAverageAge(arr) ); // (25 + 30 + 29) / 3 = 28
```

Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ So if `arr.length` is `10000` we'll have something like `10000*10000` = 100 mill

So the solution is only good for small arrays.

Further in the chapter <info:map-set-weakmap-weakset> we'll see how to optimize it.
Further in the chapter <info:map-set> we'll see how to optimize it.
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ describe("filterRangeInPlace", function() {

let arr = [5, 3, 8, 1];

filterRangeInPlace(arr, 1, 4);
filterRangeInPlace(arr, 2, 5);

assert.deepEqual(arr, [3, 1]);
assert.deepEqual(arr, [5, 3]);
});

it("doesn't return anything", function() {
assert.isUndefined(filterRangeInPlace([1,2,3], 1, 4));
});

});
});
2 changes: 1 addition & 1 deletion 1-js/05-data-types/05-array-methods/9-shuffle/solution.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ for (let key in count) {
}
```

An example result (for V8, July 2017):
An example result (depends on JS engine):

```js
123: 250706
Expand Down
55 changes: 44 additions & 11 deletions 1-js/05-data-types/05-array-methods/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,12 +234,13 @@ Now let's cover methods that search in an array.

### indexOf/lastIndexOf and includes

The methods [arr.indexOf](mdn:js/Array/indexOf), [arr.lastIndexOf](mdn:js/Array/lastIndexOf) and [arr.includes](mdn:js/Array/includes) have the same syntax and do essentially the same as their string counterparts, but operate on items instead of characters:
The methods [arr.indexOf](mdn:js/Array/indexOf) and [arr.includes](mdn:js/Array/includes) have the similar syntax and do essentially the same as their string counterparts, but operate on items instead of characters:

- `arr.indexOf(item, from)` -- looks for `item` starting from index `from`, and returns the index where it was found, otherwise `-1`.
- `arr.lastIndexOf(item, from)` -- same, but looks for from right to left.
- `arr.includes(item, from)` -- looks for `item` starting from index `from`, returns `true` if found.

Usually these methods are used with only one argument: the `item` to search. By default, the search is from the beginning.

For instance:

```js run
Expand All @@ -252,19 +253,31 @@ alert( arr.indexOf(null) ); // -1
alert( arr.includes(1) ); // true
```

Note that the methods use `===` comparison. So, if we look for `false`, it finds exactly `false` and not the zero.
Please note that `indexOf` uses the strict equality `===` for comparison. So, if we look for `false`, it finds exactly `false` and not the zero.

If we want to check if `item` exists in the array, and don't need the index, then `arr.includes` is preferred.

The method [arr.lastIndexOf](mdn:js/Array/lastIndexOf) is the same as `indexOf`, but looks for from right to left.

If we want to check for inclusion, and don't want to know the exact index, then `arr.includes` is preferred.
```js run
let fruits = ['Apple', 'Orange', 'Apple']

alert( fruits.indexOf('Apple') ); // 0 (first Apple)
alert( fruits.lastIndexOf('Apple') ); // 2 (last Apple)
```

Also, a very minor difference of `includes` is that it correctly handles `NaN`, unlike `indexOf/lastIndexOf`:
````smart header="The `includes` method handles `NaN` correctly"
A minor, but noteworthy feature of `includes` is that it correctly handles `NaN`, unlike `indexOf`:

```js run
const arr = [NaN];
alert( arr.indexOf(NaN) ); // -1 (should be 0, but === equality doesn't work for NaN)
alert( arr.indexOf(NaN) ); // -1 (wrong, should be 0)
alert( arr.includes(NaN) );// true (correct)
```
That's because `includes` was added to JavaScript much later and uses the more up to date comparison algorithm internally.
````

### find and findIndex
### find and findIndex/findLastIndex

Imagine we have an array of objects. How do we find an object with the specific condition?

Expand Down Expand Up @@ -304,7 +317,26 @@ In real life arrays of objects is a common thing, so the `find` method is very u

Note that in the example we provide to `find` the function `item => item.id == 1` with one argument. That's typical, other arguments of this function are rarely used.

The [arr.findIndex](mdn:js/Array/findIndex) method is essentially the same, but it returns the index where the element was found instead of the element itself and `-1` is returned when nothing is found.
The [arr.findIndex](mdn:js/Array/findIndex) method has the same syntax, but returns the index where the element was found instead of the element itself. The value of `-1` is returned if nothing is found.

The [arr.findLastIndex](mdn:js/Array/findLastIndex) method is like `findIndex`, but searches from right to left, similar to `lastIndexOf`.

Here's an example:

```js run
let users = [
{id: 1, name: "John"},
{id: 2, name: "Pete"},
{id: 3, name: "Mary"},
{id: 4, name: "John"}
];

// Find the index of the first John
alert(users.findIndex(user => user.name == 'John')); // 0

// Find the index of the last John
alert(users.findLastIndex(user => user.name == 'John')); // 3
```

### filter

Expand Down Expand Up @@ -389,6 +421,7 @@ Literally, all elements are converted to strings for comparisons. For strings, l
To use our own sorting order, we need to supply a function as the argument of `arr.sort()`.

The function should compare two arbitrary values and return:

```js
function compare(a, b) {
if (a > b) return 1; // if the first value is greater than the second
Expand Down Expand Up @@ -633,7 +666,6 @@ So it's advised to always specify the initial value.

The method [arr.reduceRight](mdn:js/Array/reduceRight) does the same, but goes from right to left.


## Array.isArray

Arrays do not form a separate language type. They are based on objects.
Expand All @@ -642,7 +674,7 @@ So `typeof` does not help to distinguish a plain object from an array:

```js run
alert(typeof {}); // object
alert(typeof []); // same
alert(typeof []); // object (same)
```

...But arrays are used so often that there's a special method for that: [Array.isArray(value)](mdn:js/Array/isArray). It returns `true` if the `value` is an array, and `false` otherwise.
Expand Down Expand Up @@ -733,7 +765,7 @@ A cheat sheet of array methods:
- `reduce/reduceRight(func, initial)` -- calculate a single value over the array by calling `func` for each element and passing an intermediate result between the calls.

- Additionally:
- `Array.isArray(arr)` checks `arr` for being an array.
- `Array.isArray(value)` checks `value` for being an array, if so returns `true`, otherwise `false`.

Please note that methods `sort`, `reverse` and `splice` modify the array itself.

Expand All @@ -746,6 +778,7 @@ These methods are the most used ones, they cover 99% of use cases. But there are
These methods behave sort of like `||` and `&&` operators: if `fn` returns a truthy value, `arr.some()` immediately returns `true` and stops iterating over the rest of items; if `fn` returns a falsy value, `arr.every()` immediately returns `false` and stops iterating over the rest of items as well.

We can use `every` to compare arrays:

```js run
function arraysEqual(arr1, arr2) {
return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]);
Expand Down