Map() vs for() in Javscript for looping reversely

Hi everyone,

I have an array like following:
let array = [1,2,3,4,5];

I want to loop over this array in a reverse manner and return a new array. So, my first guess was to use map(). But, I don’t know how iterate this array reversely using map(). There is a solution to this is that I have to map() by using array.reverse(). I guess, reverse() must be also looping and reversing in its logic. So, I thought I should use for() loop here where I will only be looping once(let i = array.length -1; i>=0; i++) through the array whereas if I am using map(), I have to loop twice(1. for the reverse() and 2. the map() itself).

My question is, which method is efficient and should I use map() or for() ? If someone can suggest me iterating array reversely in map() ?

Here’s how you do it:

array.reverse().map(function(...

If you don’t want to reverse the original array, you can make a shallow copy of it then map of the reversed array,

array.slice(0).reverse().map(function(...

Is there any benefit of using slice(0) over slice()?
And the second version could avoid the slice by reversing after the map. Unless the order is important for the mapping.

The argument is required for the slice method.

@GhostRoboXt, I already mentioned this method that using reverse() then map() will loop it twice. Shouldn’ t I be using for() by looping it reversely ?

@Blauelf, Yes, the order is important as I have to print it reversely. So, what is your take on map() and for() ?

@camperextraordinaire, I just want to print it. I don’t want to make any changes.

@camperextraordinaire, So if I will reverse it and then I will print it by looping over it. Doesn’t this method loops twice ? I guess reverse() must be also looping over it as well and then we will print the values again by looping after doing reverse() ? Is it efficient ? Whereas, in for() I could only loop it once by iterating reversely ?

Generally 2 linear operation vs 1 linear operation is considered to be the same in programming, so you don’t have to worry about number of operations.

There is no way map() should be used to print values in any order

@camperextraordinaire, I am creating a simple todo app without any backend. I wanted to display the recently added task in the top rather than at the last which is a default action. So, whenever, I add a task, I will push it to the array which will add the task at the bottom of the list. But, if i use unshift(), then it will add at the top of the list, but I guess, internally JS also shift the indexes so that the new item would be adjustable in the array. This action is inefficient I guess. So, I thought why not I push it in the array but display the list reversely which can actually be efficient. So, this is what I wanted to do. Please, suggest me a better approach.

@snigo, Methods:

  1. reverse() and then map()
  2. using for() reversely

So, according to you, both the methods are same. But map() cannot be used to print values in any order.

But, doesn’t the first method is loped twice but second isn’t. Doesn’t this affect the performance ?

@camperextraordinaire

React

You’ll be fine with this:

[...tasks].reverse().map(render);
// it will actually traverse tasks 3 times and that's totally fine

*By print I meant console.log, to render task you would use map to map task to it’s HTML element

@snigo, Can you please suggest any answers to this ?

I think, I will be using this.

This is actually perfect example, because this portion of the chain: map(render) is so heavy comparing to anything else it makes the following true:

[...tasks].reverse().map(render) ≈ tasks.map(render)
// Think of it like this: 5 + 10 + 10000 ≈ 10000

What about when the “tasks” are more in number ? @snigo

What kind of scale are we talking about? Let’s consider 1,000,000 shall we? I’ve never tried it but I’m pretty sure that no browser will be able to render million elements, it will just hang forever. With cloning and reversing array of million items we’re talking about sub-millisecond range for each task, so 2ms in the very worst scenario. To put it in perspective, you’re comparing tennis ball with the sun here. Adding tennis ball to the sun won’t change pretty much anything :slight_smile:

Of course, as numbers decrease difference will be less and less noticeable. Browser renders 10000 simple div elements in roughly 70ms, cloning + reversing 10000 elements in about 0.01ms. That’s still 7000x difference - tennis ball and smaller size asteroid :slight_smile:

I don’t mean the order of the results, I mean whether it is important that the map operation happens in a specific order.

.slice().reverse().map(...) might give the same result as .map(...).reverse(), but that depends on your function inside, whether it has certain kinds of side-effects.

Or you could just map through it and then with CSS reverse it, like with a flexbox or a grid.

Three options for iterating backwards without a reverse step:

// Apply the transformation function to
// the callback's return value:
array.map((_, i, arr) => arr[arr.length - 1 - i])
// Apply the transformation function to x:
array.reduce((acc, x) => [x, ...acc], [])
array.reduceRight((acc, x) => acc.concat(x), [])
1 Like