Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to skip over an element in .map()?

Tags:

javascript

How can I skip an array element in .map?

My code:

var sources = images.map(function (img) {     if(img.src.split('.').pop() === "json"){ // if extension is .json         return null; // skip     }     else{         return img.src;     } }); 

This will return:

["img.png", null, "img.png"] 
like image 834
Ismail Avatar asked Jul 17 '14 14:07

Ismail


People also ask

How do I stop a map from looping?

To break a map() loop in React: Call the slice() method on the array to get a portion of the array. Call the map() method on the portion of the array. Iterate over the portion of the array.

Can a map return null?

A map key can hold the null value. Adding a map entry with a key that matches an existing key in the map overwrites the existing entry with that key with the new entry. Map keys of type String are case-sensitive.

Can we break map in Javascript?

javascript break out of map // You cannot break out of `Array. protoype. map`.


2 Answers

Just .filter() it first:

var sources = images.filter(function(img) {   if (img.src.split('.').pop() === "json") {     return false; // skip   }   return true; }).map(function(img) { return img.src; }); 

If you don't want to do that, which is not unreasonable since it has some cost, you can use the more general .reduce(). You can generally express .map() in terms of .reduce:

someArray.map(function(element) {   return transform(element); }); 

can be written as

someArray.reduce(function(result, element) {   result.push(transform(element));   return result; }, []); 

So if you need to skip elements, you can do that easily with .reduce():

var sources = images.reduce(function(result, img) {   if (img.src.split('.').pop() !== "json") {     result.push(img.src);   }   return result; }, []); 

In that version, the code in the .filter() from the first sample is part of the .reduce() callback. The image source is only pushed onto the result array in the case where the filter operation would have kept it.

update — This question gets a lot of attention, and I'd like to add the following clarifying remark. The purpose of .map(), as a concept, is to do exactly what "map" means: transform a list of values into another list of values according to certain rules. Just as a paper map of some country would seem weird if a couple of cities were completely missing, a mapping from one list to another only really makes sense when there's a 1 to 1 set of result values.

I'm not saying that it doesn't make sense to create a new list from an old list with some values excluded. I'm just trying to make clear that .map() has a single simple intention, which is to create a new array of the same length as an old array, only with values formed by a transformation of the old values.

like image 65
Pointy Avatar answered Oct 18 '22 08:10

Pointy


Since 2019, Array.prototype.flatMap is a good option.

images.flatMap(({src}) => src.endsWith('.json') ? [] : src); 

From MDN:

flatMap can be used as a way to add and remove items (modify the number of items) during a map. In other words, it allows you to map many items to many items (by handling each input item separately), rather than always one-to-one. In this sense, it works like the opposite of filter. Simply return a 1-element array to keep the item, a multiple-element array to add items, or a 0-element array to remove the item.

like image 27
Trevor Dixon Avatar answered Oct 18 '22 08:10

Trevor Dixon