Immutable.js's map doesn't promise iteration order after a set operation. When we need a guarantee for iteration order, we can use order to map. This comes at a slight performance cost. For you, computer science people, it is amortized at an unstable O log32 N. Let's start some ordering.
I have a basic set up here with my ToDo. We're going to create an insert app function eventually. We're going to use this to sort our items. I have this other function here that is going to generate a bunch of ToDos and place them into an ordered map. We're instantiating an ordered map. We're going to place a bunch of ToDos into them, exactly 100 of them actually.
Let's see how this works. Let's go ahead and create our ToDos. Say ToDos equals generate ToDos. We will sort these ToDos by sort by number of items. We need to write this sort by number of items. Let's go up here to our function and write this out.
Sort functions must return an integer, either negative one, one, or zero. If you return negative one, it's going to compare these two items. If it's negative one, it will take the first item and give that priority over the second item. It you return one, it will do the opposite. It will give the second item priority. If you return zero, that means those items are equal and it does nothing to them.
What we're going to do is if ToDoA.items.size, we're going sort by how many items are in the ToDo because this ToDo is going to have a bunch of items, ToDo right here. ToDoA.items.size > ToDoB.items.size, we're going to return negative one.
We're going to do the opposite for the other direction. Items.size < ToDoB.items.size, we're going to return one. If they're equal which they would be at this point, we'll return zero. These will be sorted by items in a descending order. The greatest will be on top.
We can test this by writing a quick little function to iterate through all of them and make sure they're greater. We'll do var LastToDo = null. We'll do let is descending. This is what we're going to test at the end equals ToDos.every.
Every is a cool operator on an immutable structure. It will iterate over every item. ToDo, we're going to iterate over every ToDo. We're going to set is greater or equal to either is null, we're going quickly check and see if there is last ToDo. If not, don't worry about it, or the last ToDo.items.size is greater than or equal to ToDo.items.size.
I'm basically going to iterate through each of these and see if the last is greater than the next. We're going to set the last ToDo = ToDo, the current ToDo, and then we're going to return the is greater or equal. Let me do this.
Every is going to do reduce this to one value. Is descending will become a Boolean. We're going to check that Boolean. If all of them have been true, then we'll see a true value. We'll expect is descending to be true. There's something wrong with our sort function. We'll change it right here. Boom, we have a passing test.
We can easily do this in reverse. What we'll do is we'll copy this. We'll sort by descending. We can call reverse on this. It will change the direction of all those ToDos. We can copy all of our tests up here. We'll change a few things. Is descending will become is ascending.
We'll change that here, too. This will become less than or equal to. What we'll change this is to less than or equal and convert that to that. Doing reverse, we have them going in ascending order. That's pretty easy.
Something I like to do or use a lot is InsertAt. There is no InsertAt function in immutable.js. We can reproduce insert at using slice. This is useful when you're working with ordered immutables or ordered iterables.
Let's go ahead and write this out and see what it looks like. What we're going to do is create a constant. Item1 = new ToDo. We'll give it a ToDo1. We're going to copy and paste this five times. We're going to change these to three, four, five. Same here. We get this one. Five, and then two, three, four, five.
We have five ToDos. We're going to have a sixth ToDo that we're going to want to add or insert at this list. We've got to create our immutable list. Let's write ToDos = immutable.list.of and we'll type in item1, item2, item3, item4, and item5. We have a list of five.
The fourth item should be item4 now. Let's make sure that's the case. We'll do expect ToDos.get3, which is the fourth item. We'll check the ID on it to equal. We'll say item4.ID. Change this to get that right. We'll be passing test. We know that this is the fourth item.
Let's insert something between that. We'll say ToDos = InsertAt ToDos. We'll take this item6 that we have and insert it where three was. We'll do the expectation again to see what we have.
Right now, we've got nothing because insert at does not work. Let's go ahead and write this to see what this looks like. Insert at looks like this. We're going to take the first half of the immutable structure and say ToDos.slice. We'll start at this first index and we'll say index -1.
Wherever we want to insert it, we want to take the first half up into that point. We want to push the ToDo into that spot. ToDo.ID and then ToDo. We're going to do the second half. Second half = ToDos.slice. With slice, if you take the index, it will give you everything at that index and after. This is the second half minus that first half plus the ToDo we already added.
We'll then return the first half and concatenate the second half. We have an error here. That's because we didn't add the correct ToDo. We'll take item6. Now, we have a passing test. That's how you create insert at with slice. It's pretty handy little function.