DEV Community

Cover image for array.map(): A better way 🧐 ?
Jeet Mandaliya
Jeet Mandaliya

Posted on

array.map(): A better way 🧐 ?

The method map() creates a new array with the values that get returned by calling the function provided to map(anyFunctionHere) on every element of an array.

The array, on which the map() is being executed is named as calling array.

Task

Given an array with reversed first names, create a new array with the same position of names in the original array but re-reversed(should make sense) first names.

Let's take a look how we could tackle it using for-loop.

const arrayOfNames = ['anhsirK', 'nosaJ', 'nolE', 'drawdE'];

let arrayOfReversedNames = []; // declaring an empty array to store results.

for (let nameIndex = 0; nameIndex < arrayOfNames.length; nameIndex = nameIndex + 1) {
  // we can reverse a string in JavaScript with String.split("").reverse().join("")
  const reversedFirstName = arrayOfNames[nameIndex].split('').reverse().join('');
  arrayOfReversedNames.push(reversedFirstName);
}

// output: [ 'Krishna', 'Jason', 'Elon', 'Edward' ]
Enter fullscreen mode Exit fullscreen mode

In the above example, we declared arrayOfReversedNames and then appended calculated reverse names to that array.

It's time to solve the same problem, but with the use of map()method.

const arrayOfNames = ['anhsirK', 'nosaJ', 'nolE', 'drawdE'];

// declaring an empty array to store results.
let arrayOfReversedNames = arrayOfNames.map((firstName) => {
  return firstName.split("").reverse().join("")
}); 

// arrayOfReversedNames: [ 'Krishna', 'Jason', 'Elon', 'Edward' ]
Enter fullscreen mode Exit fullscreen mode

We pass in an arrow function to map() with an argument firstName. firstName will have a different value in each iteration on the elements of the calling array. Here in the first iteration, the value of firstName would be anhsirK, nosaJ in the second iteration, and so on... It's clear that we get the same results because map() is also doing the same iteration that for-loop was doing.

At this point you might ask if both methods are doing the same thing that is iteration over elements of the calling array, shouldn't we use for-loop instead of map()? It's more readable and explicitly describes what is being done there.

Well, yes and no.

Benefits of using map() over for-loop

  • Fewer lines of code - mostly better!
  • We get access to individual elements of the calling array directly with an argument in the function passed on to map() - far easier than always getting values with callingArray[someIndex].
  • A certainty that all elements of the array will be iterated with map() - never deal with wrong indices inside a for-loop anymore.

All we know at the end of the day is that when we have an array and we want to process every element of that array and store values in a new one, map() is the way to go.


This is originally written at my blog


Edit:

Take a look at the comment on this post made by Brett Thurston to get more info on where not to use map() as per MDN.

Top comments (13)

Collapse
 
marceliwac profile image
Marceli-Wac

I'm not sure I see the value here, provided it's just syntactical difference (it's not, see the other comments). If it were just a matter of syntactical sugar, this whole post could have been addressed by bringing the Array.forEach() to Author's attention, which in the simpler terms, is an "Array.map()"-like syntax for for-loop.

i.e.

newArray = [];

oldArray.forEach((element, index, thisArray) => {
   // Access the index of the current element
   console.log("Handling element at", index, "index of old array");

   // Work on the current element of the array
   newArray.push(transformElement(element));

   // Access the elements of the current array at specific index:
   thisArray[index] = {...element, transformed: true}
}
Enter fullscreen mode Exit fullscreen mode

The main benefit of taking thisArray as the last argument to lambda is the fact that you can encapsulate the behaviour in a named function (here a lambda is provided). Rest is pretty obvious.

Collapse
 
sereneinserenade profile image
Jeet Mandaliya

In the task I mentioned above for reversing strings and putting them in a new array, I agree that forEach is a good approach.

I personally would still prefer map() over forEach() because

  1. we don't have to push element to newArray manually
  2. since map() returns an array. we can do further processing on array like filtering and sorting right there after running map() without ever need to manipulate newArray.

For example.

const oldArr: string[] = ['anhsirK', 'nosaJ', 'nolE', 'drawdE']
const newArray: string[] = oldArr.map((element) => element.split("").reverse().join("")).sort((a, b) => a > b ? 1 : -1)
Enter fullscreen mode Exit fullscreen mode
Collapse
 
marceliwac profile image
Marceli-Wac

totally agree!

Collapse
 
ravavyr profile image
Ravavyr

It's not a bad approach, but MAP should be used for simple events, most of the time when you loop through an array you're going to be doing a lot more than just one thing. In those cases, use a for loop if you don't want to hate yourself six months later.

Also your naming convention is what makes your for loop harder to read.

This is far simpler to understand, now, AND in six months versus the MAP method.

const names = ['anhsirK', 'nosaJ', 'nolE', 'drawdE'];

let reversednames = [];

for (let i = 0; i < names.length; i++) {
const reversedname = names[i].split('').reverse().join('');
reversednames.push(reversedname);
}

/Disclaimer/
I'm super anti-camelcase. Using lowercase names and keeping them short makes your code immediately easier to read, plus you will NEVER have a syntax bug because you typo'd an uppercase letter, so hours saved. You can use underscores if needed.
Was it not for the example above being descriptive i'd probably just go with
"revs" in place of "reversednames" and "rname" in place of "reversedname".
Just to simplify the code more.
Your variable names should not overtake the logic visibly.

Collapse
 
andrewbridge profile image
Andrew Bridge

I think there's a balance to be struck in terms of maintainability when naming variables. Sure, overly verbose variable names are clunky and can make things harder to read, but on the other hand revs and rname a) gives me no context (is revs something about revolutions?) and b) can be easily misread (looks a quite similar to mame).

I think with IDEs, things like typos become far less of a problem, so I'd personally stay away from lots of abbreviations.

I also think that this specific task fits quite well with your suggestion of what .map() should be used with. It's short, single manipulation and, with proper naming and shorthand functions, is quite succinct:

reversedNames = names.map(name => name.split('').reverse().join(''))

Collapse
 
sereneinserenade profile image
Jeet Mandaliya

I also agree with you that with the modern age of IDEs and linters, typos have become far less of a problem unless we're doing something over ssh on a raspberry pi and have to use vim or nano. But if I am to do real programming on ssh, I would prefer using vscode remote containers mode and code there rather programming in vim / nano on over ssh.

Thread Thread
 
andrewbridge profile image
Andrew Bridge

Don't let the vim enthusiasts hear that! You'll be stuck for hours as they tell you the 9000 ways of making vim fully sentient and writing the code for you haha!

Thread Thread
 
sereneinserenade profile image
Jeet Mandaliya

True to that. I've done that many times myself as I am a big VIM fan and even use VSCode vim mode today. I've used it as my main developing software for a year but the problem begun when I started working professionally as a fronend dev, other people were using .editorconfig and prettier and stuff which I found were a bit ( for me ) cumbersome to implement and therefore I switched to VSCode. Though my love for Vim and it's ways to handle things is eternal.

Collapse
 
sereneinserenade profile image
Jeet Mandaliya

For smaller logics, having a for-loop is no problem at all, but as I mentioned here, we have logics were we're doing multiple processes on array like sorting/filtering/reducing to one value, map() is imo better as we can do it in one place.

Also array methods like map() and filter() and reduce() are an integral part of todays frontend development as no backend gives us all the customization we want in the response and thus we always have to manipulate data in frontend and same as for-loop or forEach loop, these array methods are integral part of processing the data in frontend so a developer imo should be enough familiar with these methods to even understand code that he has not written. ( to be noted that I am not supporting bad code styles or anything here ).

And libraries like Lodash came into existence for the need of finding and creating and manipulating data and with it's API where we can chain processing to be done on array, it makes our work a lots of easier than writing a for loop every time we want to execute certain processes on an array.

Collapse
 
brettthurs10 profile image
Brett Thurston • Edited

I just wrote a primer on the map method and in full disclosure, I've been using map as replacements for loops. MDN says, that shouldn't be used in that case and ONLY use it if you intended to use the array returned from the method.

dev.to/brettthurs10/grab-your-map-...

MDN bit:
developer.mozilla.org/en-US/docs/W...

dev-to-uploads.s3.amazonaws.com/i/...

Collapse
 
sereneinserenade profile image
Jeet Mandaliya

Thanks for sharing Brett, I loved that example of user cards.

I've mentioned in the Task description mentioned in the post that we need to create a new array, so that should be no problem for using map(). Even though I will mention your comment in my post so readers can have a better look at info you provided here.

Collapse
 
patarapolw profile image
Pacharapol Withayasakpunt

for ... of is handy when serialize await async.

Explicit iteration for (classical for)? I rarely need to use it.

Collapse
 
sereneinserenade profile image
Jeet Mandaliya

Yess, ES6 has been a boon for us.