Why does JavaScript map function return undefined?

Javascript

Javascript Problem Overview


My code

 var arr = ['a','b',1];
 var results = arr.map(function(item){
                if(typeof item ==='string'){return item;}  
               });

This gives the following results

["a","b",undefined]

I don't want undefined in the results array. How can I do it?

Javascript Solutions


Solution 1 - Javascript

You aren't returning anything in the case that the item is not a string. In that case, the function returns undefined, what you are seeing in the result.

The map function is used to map one value to another, but it looks like you actually want to filter the array, which a map function is not suitable for.

What you actually want is a filter function. It takes a function that returns true or false based on whether you want the item in the resulting array or not.

var arr = ['a','b',1];
var results = arr.filter(function(item){
    return typeof item ==='string';  
});

Solution 2 - Javascript

Filter works for this specific case where the items are not modified. But in many cases when you use map you want to make some modification to the items passed.

if that is your intent, you can use reduce:

var arr = ['a','b',1];
var results = arr.reduce((results, item) => {
	if (typeof item === 'string') results.push(modify(item)) // modify is a fictitious function that would apply some change to the items in the array
	return results
}, [])

Solution 3 - Javascript

Since ES6 filter supports pointy arrow notation (like LINQ):

So it can be boiled down to following one-liner.

['a','b',1].filter(item => typeof item ==='string');

Solution 4 - Javascript

My solution would be to use filter after the map.

This should support every JS data type.

example:

const notUndefined = anyValue => typeof anyValue !== 'undefined'    
const noUndefinedList = someList
          .map(// mapping condition)
          .filter(notUndefined); // by doing this, 
                      //you can ensure what's returned is not undefined

Solution 5 - Javascript

You can implement like a below logic. Suppose you want an array of values.

let test = [ {name:'test',lastname:'kumar',age:30},
             {name:'test',lastname:'kumar',age:30},
             {name:'test3',lastname:'kumar',age:47},
             {name:'test',lastname:'kumar',age:28},
             {name:'test4',lastname:'kumar',age:30},
             {name:'test',lastname:'kumar',age:29}]

let result1 = test.map(element => 
              { 
                 if (element.age === 30) 
                 {
                    return element.lastname;
                 }
              }).filter(notUndefined => notUndefined !== undefined);

output : ['kumar','kumar','kumar']

Solution 6 - Javascript

You only return a value if the current element is a string. Perhaps assigning an empty string otherwise will suffice:

var arr = ['a','b',1];
var results = arr.map(function(item){
    return (typeof item ==='string') ? item : '';  
});

Of course, if you want to filter any non-string elements, you shouldn't use map(). Rather, you should look into using the filter() function.

Solution 7 - Javascript

var arr = ['a','b',1];
var results = arr.filter(function(item){
                if (typeof item ==='string') {return item;}  
               });

Solution 8 - Javascript

If you have to use map to return custom output, you can still combine it with filter.

const arr = ['a','b',1]

const result = arr.map(element => {

  if(typeof element === 'string')
    return element + ' something'

}).filter(Boolean) // this will filter out null and undefined

console.log(result) // output: ['a something', 'b something']

Solution 9 - Javascript

If you use it like this, your problem will be solved. Also, you will have a clean and short code

var _ = require('lodash'); //but first, npm i lodash --save
var arr = ['a','b',1];
var results = _.compact(
    _.map(arr, function(item){
        if(_.isString(item)){return item;}
    }
); //false, null, undefined ... etc will not be included

with ES6...

const _ = require('lodash'); //but first, npm i lodash --save
const arr = ['a','b',1];
const results = _.compact(
    _.map(arr, item => {
        if(_.isString(item)){return item;}
    }
);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAkshat Jiwan SharmaView Question on Stackoverflow
Solution 1 - JavascriptIkkeView Answer on Stackoverflow
Solution 2 - JavascriptNicola PedrettiView Answer on Stackoverflow
Solution 3 - JavascriptMatas VaitkeviciusView Answer on Stackoverflow
Solution 4 - JavascriptJojo NarteView Answer on Stackoverflow
Solution 5 - JavascriptmkumarView Answer on Stackoverflow
Solution 6 - JavascriptBenMView Answer on Stackoverflow
Solution 7 - JavascriptPrasath KView Answer on Stackoverflow
Solution 8 - JavascriptFatih BulutView Answer on Stackoverflow
Solution 9 - Javascriptkahraman karayelView Answer on Stackoverflow