This lesson is for PRO members.

Unlock this lesson NOW!
Already subscribed? sign in

Iterating Over an Immutable.js Map()

6:31 JavaScript lesson by

Immutable.js provides several methods to iterate over an Immutable.Map(). These also apply to the other immutable structures found within the Immutable.js family, such as Set and List. The primary methods are map and forEach, but we will also cover filter and groupBy.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

Immutable.js provides several methods to iterate over an Immutable.Map(). These also apply to the other immutable structures found within the Immutable.js family, such as Set and List. The primary methods are map and forEach, but we will also cover filter and groupBy.

Avatar
Noah

I am not sure why it is possible to do the stuff you do in markAllTodosAsComplete - doesn't this show that the Map is in fact not immutable?

In reply to egghead.io
Avatar
J.S.

Hey Noah! It shows that regular javascript objects remain mutable inside the immutable structure, but the structure itself cannot be mutated. It's somewhat confusing, I know. If you wanted everything to be immutable, then you'd need to make the Todos into Map()s themselves. Also that is using forEach(), which can produce side effects. Does that make sense?

In reply to Noah
Avatar
Sandeep

"return" is not required in the first line of markAllTodosAsComplete as we're not assigning the returned value back to todos. I know it doesn't matter but might avoid some confusion.

Avatar
Sandeep

Make the Todos into Map()s themselves -OR- use fromJS().

In reply to J.S.
Avatar
Ilyes

You could also use map instead of foreach:

function markAllTodosAsComplete(todos) {
    return todos.map(todo => {
        todo.completed = true;
        return todo;
    });
}
Avatar
Vlado Tesanovic

Function addTodo does not add elements in right order. In your example, you use getTodoTexts, and you are expecting text that is same on all objects "I'm a todo!", but try with to change getTodoTexts to return title instead of text, and try to fetch .first() element then expect "Todo0", it will fail and you will see that is not consistent.

Avatar
J.S.

Hi Vlado!

That's correct and expected. Immutable.Map() is unordered. If you need want order (at the cost of some performance) use Immutable.OrderedMap(). Here's a link to the docs: https://facebook.github.io/immutable-js/docs/#/OrderedMap

Thanks!
Leonard

In reply to Vlado Tesanovic

Immutable.js provides several methods to iterate over an Immutable Map. These also apply to the other Immutable structures found within the Immutable.js family, such as Set and List.

The primary methods of iteration are Map and forEach. But we're also going to cover Filter and Group by.

At the top here, we've got our basic Mocha setup todo, that's going to structure out todos, and a convenience method that will add todos to our Immutable Map.

We have four methods that we're going to fill in here in a second, that will pass these tests. Let's take a look at these tests. All right.

This test here is saying, let's convert all todos into a map of titles. All right? We have our todos and they're being instantiated as a map. This is going ot be the same for most of these tests, so this code is very repetitive. Then we're going to add 10 todos to these todos.

Now, let's write a method that will grab the text property from each using Map. The method will be get todo texts. OK? That's going to be up here. Let's go ahead and write this.

Now, how do we use Map? Well, we're going to take the Immutable Map, which is called todos here, and there has a method called Map.

Now Map accepts a function, and that function, whatever it returns, will create a new type of Immutable, a new Immutable Map for that matter.

Let's pass in a function. The function has one parameter and that is whatever we're going to iterate over, which are the todos. Each todo will be passed into the function. We have todo and it's passed into the function.

Inside the function, we just want to return the text. We're going to return todo.text.

Let's go back down here. Let's see what happened here. We applied the method to the todos and we got a new Immutable Map. This is a map that was returned. The first Immutable is now a string called I'm a todo, which is what we returned from the Map method. That's how map works. It transforms an iterable into something else, whatever you return back.

Say we don't want some of the todos. Well, we can use the Filter method, OK? We're doing the same thing here, but we do have a little bit of a twist on this. Let me make this a little bit bigger.

The twist is, as we're adding these todos, we're going to set half of them to be incomplete, because the third parameter in the instantiation for the todos says if it's complete or not. Half of these are going to be incomplete. We're going to have to write a get completed todos method using filter. OK?

Let's go up top, to the get Filter method, or the get completed todos method and write this out. Again, we take the todos, Map iterable, then we use the Filter method, which also accepts, just like Map, a function that will have each todo passed into it.

Let's go ahead and write a function for this. OK?

Now, we want to return false for the things we do not want returned to the new iterable. OK? For that, we will just do return, the ones that are only completed, so return.completed. OK? That's now only going to return, it's going to filter out all the incomplete ones, because the incomplete ones are going to be false.

Let's go back down to get completed todos, and we'll see now that the Filter todo size is equal to five, which is half of the original amount, and we see the tests passing.

Now, Immutable.js is pretty strong about keeping things Immutable. But it does offer one function that will mutate each child in the map, or in any of the iterables.

This can produce side effects. You want to be careful with this, but it is there and it's a good thing to go over.

I want you to see here that I've, we're going to writing a method called Mark all todos as complete, and you'll notice that it does not return, it does not return another Immutable, because it's actually affecting the children inside of the todos.

Let's go ahead and take a look at what that looks like.

Since we don't have to return anything and it's just going to iterate over each child, we can get rid of that return statement.

We're going to use the forEach method, which surprise, surprise, accepts the same kind of function signature that we had in the other Filter and Map functions. Its going to pass in each child, each item inside of the todos into this function and you can have your way with it.

What we want to do is mark all of them as completed. We'll do todo.completed equals true. When we do that, go back down to the test. You can see now, we're going to convert these two in array, we're going to iterate over all of them. We're going to see if these are equal to true, and sure enough, the test is passing.

Last but not least, we've got the Group by operator. That allows us group items within an Immutable into other Immutable structures.

What we want to do here is group these by true and false. We're going to create two new keys. We're going to split apart this todos into a new Immutable, that has two keys of true and false. We're going to see if those are equal to five. We're going to split this in half, essentially, and we're using the same modulation to create the completed todos.

Let's go ahead and write this method. Group todos by completed. We'll go back up top, this time we will return something because it is an Immutable method. We're going to take the todos, we're going to do todos.group by, which is the operator, same method signature as before. OK. We're going to, and inside this method signature we're going to return todo.completed.

Now, this does something rather interesting. What it's going to do is basically going to create a new key based on these guys. OK, so it's going to create a new key based on what this is returned as.

It's going to return true, and then it's going to take that todo and place it under that new key. For every true todo, it's going to create a new Immutable map that is going to contain all the todos that are either completed or incomplete. Let's take a look and see how that works down here.

Well, as we can see, we have one test that says, give me the group todos that have a key of true, and give me their size. We have a size of five, because there are only five completed todos, and the same for thing for the false. We have five incomplete todos, and now you see all the tests pass.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?