admin管理员组文章数量:1129437
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?
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?
13 Answers
Reset to default 251You 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';
});
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
}, [])
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']
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');
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
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']
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.
var arr = ['a','b',1];
var results = arr.filter(function(item){
if (typeof item ==='string') {return item;}
});
I run into this quite frequently where the type after filtering will still be string | number
. So, to expand upon these solutions and include type safety you can use a user-defined type guard.
https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
const result = ['a','b',1].filter((item) => typeof item ==='string');
// result is typed as (string | number)[]
Better type safety using user-defined type guard
const result = ['a','b',1].filter((item): item is string => typeof item ==='string');
// result is now typed as string[]
The problem:
the issue is arr.map()
will do a full iteration of arr
array length, i.e. map()
method will loop as much as the length of arr
is, no matter what condition you have inside it, so if you defined a condition inside it e.g. if(typeof item ==='string'){return item;}
even if the condition is not happening, the map()
will be forced to keep looping until finishing the looping of the whole arr
so it will give you undefined
for the rest of elements if the condition is not met.
The solutions:
Solution One: if you want to return the whole item in the array when the condition is met, you can use arr.filter()
so the filter will return the whole item for the iteration e.g. if you have array of objects like bellow
const arr = [{name: "Name1", age: 25}, {name: "Name2", age: 30}, {name: "Name3", age: 25}]
and you want to return the whole objects when the condition is met like example below
const filteredItems = arr.filter((item)=>{if(item.age === 25){return true}})
console.log(filteredItems) //results: [{name: "Name1", age: 25}, {name: "Name3", age: 25}]
conclusion: filter()
method returns an array of the whole items in it if the condition is met.
Solution Two: if you want to return only a specific data of the objects (or the whole object or any shape of data) in array i.e. if you want to return only the names in array without the ages, you can do this
const namesOnly = arr.map((item)=>{if(item.age === 25){return item.name}})
console.log(namesOnly) //results: ["Name1, udefined, "Name3"]
now to remove the undefined
you just use filter()
method on the results like below
const namesOnly = arr.map((item)=>{if(item.age === 25){return item.name}}).filter((item)=> !!item)
console.log(namesOnly) //results: ["Name1, "Name3"]
conclusion: map()
method returns an array of specifically defined data in the return, and returns undefined
if the condition is not met. so then we can use filter()
method to remove the undefined
.
Map is used when you want to produced new modified array from the original array. the simple answer may be for someone
var arr = ['a','b',1];
var results = arr.filter(function(item){
// Modify your original array here
return typeof item ==='string';
}).filter(a => a);
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;}
}
);
You can filter records with .map
easily using below example code
const datapoints = [
{
PL_STATUS: 'Packetloss',
inner_outerx: 'INNER',
KPI_PL: '97.9619'
},
{
PL_STATUS: 'Packetloss',
inner_outerx: 'OUTER',
KPI_PL: '98.4621',
},
{
PL_STATUS: 'Packetloss',
inner_outerx: 'INNER',
KPI_PL: '97.8770',
},
{
PL_STATUS: 'Packetloss',
inner_outerx: 'OUTER',
KPI_PL: '97.5674',
},
{
PL_STATUS: 'Packetloss',
inner_outerx: 'INNER',
KPI_PL: '98.7150',
},
{
PL_STATUS: 'Packetloss',
inner_outerx: 'OUTER',
KPI_PL: '98.8969'
}
];
const kpi_packetloss_inner: string[] = [];
datapoints.map((item: { PL_STATUS: string; inner_outerx: string; KPI_PL: string }) => {
if (item.PL_STATUS === 'Packetloss' && item.inner_outerx === 'INNER') {
kpi_packetloss_inner.push(item.KPI_PL);
}
})
console.log(kpi_packetloss_inner);
本文标签: Why does JavaScript map function return undefinedStack Overflow
版权声明:本文标题:Why does JavaScript map function return undefined? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736742296a1950578.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
undefined
. What do you expect to return if it's not a string? An empty string? – BenM Commented Apr 16, 2013 at 12:28