Why map() Is My Go-To Array Method
The first time I had to turn one list into another list, I wrote a for loop. Of course I did, that was the only tool I had. I had an array of names, I needed an array of list items, so I made an empty array, looped, pushed, and returned the new one. It worked. I did it that way for months, in every little project, and I thought that was just what programming looked like. (I also got the index wrong by one more than once, and spent an embarrassing amount of time staring at an off-by-one before I spotted it.)
Then someone showed me map, and the loop collapsed into one line. Same result, no empty array, no push, no index variable to get wrong. It felt like cheating for about a week, then it felt like the obvious way to do it, and I have reached for it first ever since.
the loop version and the map version
Here is the shape I used to write, turning an array of guest names into an array of greeting strings:
const guests = ['Sarah', 'Michael', 'Amira'];
const greetings = [];
for (let i = 0; i < guests.length; i++) {
greetings.push('Hi, ' + guests[i]);
}
console.log(greetings);
// ['Hi, Sarah', 'Hi, Michael', 'Hi, Amira']And here is the same thing with map:
const guests = ['Sarah', 'Michael', 'Amira'];
const greetings = guests.map((guest) => 'Hi, ' + guest);
console.log(greetings);
// ['Hi, Sarah', 'Hi, Michael', 'Hi, Amira']map takes a function, runs it on every item, and collects the results into a new array. The original array stays untouched, which matters more than it sounds like it does. The loop version can quietly mutate things if you are careless with it; the map version hands you a fresh array by construction. The callback gets three arguments, the item, its index, and the whole array, and the index one is the quiet hero. Numbering a list, for example, is just the index plus one:
const guests = ['Sarah', 'Michael', 'Amira'];
const seating = guests.map((guest, index) => ({
name: guest,
table: index + 1,
}));
console.log(seating);
// [
// { name: 'Sarah', table: 1 },
// { name: 'Michael', table: 2 },
// { name: 'Amira', table: 3 },
// ]One detail worth knowing: the result always has the same length as the input. Every item goes in, one result comes out. map is for transforming, not for deciding what stays. When I want side effects instead of a new array, like logging each item or saving each one, forEach is the honest tool for that job. Mixing the two up is how you end up with a map call whose return value nobody reads, which is a forEach wearing a costume.
when some items need a different result
Real lists are rarely uniform. Say a few guests are VIPs and their greeting should say so. The condition lives inside the callback, a plain ternary, nothing fancy:
const guests = [
{ name: 'Sarah', vip: true },
{ name: 'Michael', vip: false },
{ name: 'Amira', vip: true },
];
const greetings = guests.map((guest) =>
guest.vip ? 'Welcome back, ' + guest.name : 'Hi, ' + guest.name
);
console.log(greetings);
// ['Welcome back, Sarah', 'Hi, Michael', 'Welcome back, Amira']This is the conditional mapping the topic promises, and it covers most days. But sometimes the condition is not about a different result, it is about no result at all. Some guests should not be on the list. There are two clean ways to handle that, and I use both.
The first is filter then map, two passes, easy to read:
const guests = ['Sarah', 'Michael', 'Amira', 'Jon'];
const longNames = guests
.filter((guest) => guest.length > 4)
.map((guest) => guest.toUpperCase());
console.log(longNames);
// ['SARAH', 'MICHAEL', 'AMIRA']The second is flatMap, which is map plus one level of flattening. If the callback returns an empty array for an item, that item vanishes from the result. One pass, same outcome:
const guests = ['Sarah', 'Michael', 'Amira', 'Jon'];
const longNames = guests.flatMap((guest) =>
guest.length > 4 ? [guest.toUpperCase()] : []
);
console.log(longNames);
// ['SARAH', 'MICHAEL', 'AMIRA']I reach for filter plus map when I am reading the code later and want the intent obvious, and flatMap when the mapping and the condition belong together in one thought. Either way, the rule holds: map on its own keeps every item, so when something needs to disappear, that is a second method's job.
where i use it most: rendering lists in react
If you write React, you already use map every day, probably without thinking of it as the array method anymore. It is just how a list becomes JSX:
type Guest = { id: number; name: string; table: number };
function GuestList({ guests }: { guests: Guest[] }) {
return (
<ul>
{guests.map((guest) => (
<li key={guest.id}>
{guest.name} (Table {guest.table})
</li>
))}
</ul>
);
}The key is the part people skip and then debug for an hour. React uses it to tell list items apart when the list changes, so it should be a stable id from your data, not the index. An index key works until the list reorders or an item is removed from the middle, and then the wrong row keeps the wrong state, and you get to learn that lesson the way I did, by watching a checkbox stay checked on the wrong name.
- Sarah Chen
- Michael Okafor
- Amira Yusuf
- Jon Park
- Zohan Ali
- Rose Patel
map did not make me a better programmer overnight. It just removed a whole category of small mistakes from my day, the empty array I forgot to declare, the push I forgot to write, the index that was off by one. These days, when I catch myself writing a loop that builds a new array, I stop and reach for map instead. The loop still has its place, but building a new list from an old one is map's job, and it does that job in one line.