Skip to content

[V3] Elyses Looping Enchantments: fix everything around this exercise #1097

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Aug 31, 2021
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
4 changes: 2 additions & 2 deletions concepts/array-loops/.meta/config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"blurb": "TODO: add blurb for array-loops concept",
"authors": ["rishiosaur"],
"blurb": "Learn about multiple ways to iterate over arrays in JavaScript.",
"authors": ["rishiosaur", "junedev"],
"contributors": ["SleeplessByte"]
}
111 changes: 83 additions & 28 deletions concepts/array-loops/about.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,101 @@
# About

In JavaScript, looping over `Array`s is extremely common, seeing as they are some of the most widely-used and efficient structures to store data.
When working with arrays, you sometimes want to execute code for each value in the array.
This is called iterating or looping over the array.

Looping over an array doesn't need to be accomplished using a `for` loop. JavaScript provides various methods that handle some of the more common use cases for array looping in a more idiomatic way, such as `Set`s, `Array.prototype.some`, and `Array.prototype.every`, as well as some immutable state prototypal functions.
Here we will look at the case where you do not want to modify the array in the process.
For transforming arrays, see [Concept Array Transformations][concept-array-transformations] instead.

## JavaScript Sets
## The `for` Loop

Like in mathematics, a `Set` is a collection of unique values. Typecasting to a Set to get a list of unique items is possible:
The most basic and usually very performant way to iterate over an array is to use a `for` loop, see [Concept For Loops][concept-for-loops].

```js
const numbers = [1, 1, 2, 3, 4, 5, 5, 7]
```javascript
const numbers = [6.0221515, 10, 23];

// Goal: a function that changes the above array into an array of unique values (i.e. removes duplicates)
for (let i = 0; i < numbers.length; i++) {
console.log(numbers[i]);
}
// => 6.0221515
// => 10
// => 23
```

// This is a function that uses a for .. of loop
const makeNumbersUniqueLoop = (arr) => {
var temp = []
## The `for...of` Loop

for (const v of arr) {
if (arr.indexOf(v) === -1 && v !== '') {
temp.push(v)
}
}
When you want to work with the value directly in each iteration and do not require the index at all, you can use a `for .. of` loop.

return temp
}
`for...of` works like the basic `for` loop shown above, but instead of having to deal with the _index_ as variable in the loop, you are provided directly with the _value_.

// This is a function that uses array-transformations
const makeNumbersUniqueTransform = (arr) => {
return arr.filter((item, index, self) => self.indexOf(item) === index))
```javascript
const numbers = [6.0221515, 10, 23];

// Because re-assigning number inside the loop will be very
// confusing, disallowing that via const is preferable.
for (const number of numbers) {
console.log(number);
}
// The equivalent function using Sets and spread syntax
const makeNumbersUniqueSet = (a) => [...new Set(a)]
// => 6.0221515
// => 10
// => 23
```

Just like in regular `for` loops, you can use `continue` stop the current iteration and `break` to stop the execution of the loop entirely.

JavaScript also has a `for...in` loop, for example to iterate over keys in an object.
It is important to note that `for...of` and `for...in` are not interchangeable, see [MDN documentation][mdn-for-in-for-of] for details on this.

## The `forEach` Method

Every array includes a `forEach` method that can also be used to loop over it.

`forEach` accepts a [callback][concept-callbacks] as parameter.
The callback function is called once for each element in the array.

```javascript
const numbers = [6.0221515, 10, 23];

numbers.forEach((number) => console.log(number));
// => 6.0221515
// => 10
// => 23
```

Using a different data structures can lead to cleaner and _intentional_ code. The upside of using a `Set` is that new elements are also considered for uniqueness, unlike the one-off loop variants.
In the example above the callback only uses the current element as parameter.
But if needed, the callback can make use of up to three parameters.

- the value of the current iteration
- the index of the current iteration
- the entire array

```javascript
const numbers = [6.0221515, 10, 23];

function callback(number, index, fullArray) {
console.log(number, index, fullArray);
}

numbers.forEach(callback);
// => 6.0221515 0 [ 6.0221515, 10, 23 ]
// => 10 1 [ 6.0221515, 10, 23 ]
// => 23 2 [ 6.0221515, 10, 23 ]
```

## `for .. of` and Iterators
Besides the callback, `forEach` accepts the `this` context to use for the iteration as optional second parameter.
You can see an example in the ["Using thisArg" section on MDN][mdn-foreach-thisarg].

Although `for .. of` has been introduced as a method for iterating over an `Array`, it can also be used for other classes that extend the `Iterator` class, like generator functions, `Set`s, and so on.
There are a couple of things you should keep in mind when working with `forEach`.

## Interesting Links
- There is no way to stop the iteration once the `forEach` loop was started.
The statements `break` and `continue` do not exist it this context.
- `forEach` behaves weirdly if you modify the array after starting the loop.
Elements you add to the end will be ignored, removing elements can lead to others being skipped, etc.
To avoid these kinds of issues, never modify the underlying array in the callback.
- The return value of the `forEach` method itself is `undefined`.
Because of that, you cannot chain any other array methods at the end.
- If you need to optimize your code for performance, you should use `for` or `for...of` instead as they are around three times faster.

- [MDN Documentation for Array and its prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
- [Array functions cheatsheet](https://dmitripavlutin.com/operations-on-arrays-javascript/)
[concept-array-transformations]: /tracks/javascript/concepts/array-transformations
[concept-for-loops]: /tracks/javascript/concepts/for-loops
[concept-callbacks]: /tracks/javascript/concepts/callbacks
[mdn-foreach-thisarg]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#using_thisarg
67 changes: 66 additions & 1 deletion concepts/array-loops/introduction.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,68 @@
# Introduction

TODO: add introduction for array-loops concept
When working with arrays, you sometimes want to execute code for each value in the array.
This is called iterating or looping over the array.

Here we will look at the case where you do not want to modify the array in the process.
For transforming arrays, see [Concept Array Transformations][concept-array-transformations] instead.

## The `for` Loop

The most basic to iterate over an array is to use a `for` loop, see [Concept For Loops][concept-for-loops].

```javascript
const numbers = [6.0221515, 10, 23];

for (let i = 0; i < numbers.length; i++) {
console.log(numbers[i]);
}
// => 6.0221515
// => 10
// => 23
```

## The `for...of` Loop

When you want to work with the value directly in each iteration and do not require the index at all, you can use a `for .. of` loop.

`for...of` works like the basic `for` loop shown above, but instead of having to deal with the _index_ as variable in the loop, you are provided directly with the _value_.

```javascript
const numbers = [6.0221515, 10, 23];

// Because re-assigning number inside the loop will be very
// confusing, disallowing that via const is preferable.
for (const number of numbers) {
console.log(number);
}
// => 6.0221515
// => 10
// => 23
```

Just like in regular `for` loops, you can use `continue` stop the current iteration and `break` to stop the execution of the loop entirely.

## The `forEach` Method

Every array includes a `forEach` method that can also be used to loop over it.

`forEach` accepts a [callback][concept-callbacks] as parameter.
The callback function is called once for each element in the array.
The current element, its index and the full array are provided to the callback as arguments.
Often, only the first or the first two are used.

```javascript
const numbers = [6.0221515, 10, 23];

numbers.forEach((number, index) => console.log(number, index));
// => 6.0221515 0
// => 10 1
// => 23 2
```

There is no way to stop the iteration once the `forEach` loop was started.
The statements `break` and `continue` do not exist it this context.

[concept-array-transformations]: /tracks/javascript/concepts/array-transformations
[concept-for-loops]: /tracks/javascript/concepts/for-loops
[concept-callbacks]: /tracks/javascript/concepts/callbacks
11 changes: 10 additions & 1 deletion concepts/array-loops/links.json
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
[]
[
{
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of",
"description": "MDN: for...of"
},
{
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach",
"description": "MDN: forEach"
}
]
14 changes: 14 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,20 @@
"prerequisites": ["arrays", "functions", "objects"],
"status": "beta"
},
{
"slug": "elyses-looping-enchantments",
"name": "Elyses Looping Enchantments",
"uuid": "e06f8f70-019f-4cec-924b-3971414e15d9",
"concepts": ["array-loops"],
"prerequisites": [
"arrays",
"callbacks",
"arrow-functions",
"for-loops",
"conditionals"
],
"status": "beta"
},
{
"slug": "nullability",
"name": "Employee Badges",
Expand Down
19 changes: 0 additions & 19 deletions exercises/concept/array-loops/.docs/hints.md

This file was deleted.

50 changes: 0 additions & 50 deletions exercises/concept/array-loops/.docs/instructions.md

This file was deleted.

65 changes: 0 additions & 65 deletions exercises/concept/array-loops/.docs/introduction.md

This file was deleted.

11 changes: 0 additions & 11 deletions exercises/concept/array-loops/.meta/config.json

This file was deleted.

Loading