为什么 JavaScript 映射函数返回未定义的?

我的原则

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

这给出了以下结果

["a","b",undefined]

我不希望 undefined出现在结果数组中。我该怎么做呢?

203716 次浏览

如果该项不是字符串,则不返回任何内容。在这种情况下,函数返回 undefined,也就是您在结果中看到的内容。

Map 函数用于将一个值映射到另一个值,但是看起来您实际上想要筛选数组,而 map 函数不适合筛选数组。

实际上需要的是一个 过滤器函数。它接受一个函数,该函数根据您是否希望该项出现在结果数组中来返回 true 或 false。

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

只有当前元素是 string时才返回一个值。也许分配一个空字符串就足够了:

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

当然,如果要过滤任何非字符串元素,则不应使用 map()。相反,您应该考虑使用 filter()函数。

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

由于 ES6 filter支持尖端箭头符号(如 LINQ) :

因此,它可以归结为以下一行程序。

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

筛选器适用于项目未被修改的特定情况

如果这是你的意图,你可以使用 减少:

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
}, [])

我的解决方案是使用过滤器后的地图。

这应该支持每种 JS 数据类型。

例如:

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

您可以像下面的逻辑一样实现。 假设您想要一个值数组。

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']

如果必须使用 map 来返回自定义输出,仍然可以将它与 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']

如果你这样使用它,你的问题就解决了。 而且,您将拥有一个简洁的代码

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

和 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;}
}
);

我经常遇到这种情况,过滤后的类型仍然是 string | number。因此,要扩展这些解决方案并包括类型安全,可以使用用户定义的类型保护。 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)[]

使用用户定义的类型保护更好的类型安全

const result = ['a','b',1].filter((item): item is string => typeof item ==='string');
// result is now typed as string[]

问题是: 问题是 arr.map()会对 arr数组长度做一个完整的迭代,也就是说,无论你在 arr内部有什么条件,map()方法都会循环 arr的长度,所以如果你在它内部定义了一个条件,例如 if(typeof item ==='string'){return item;},即使这个条件没有发生,map()也会被迫保持循环直到完成整个 arr的循环,所以如果条件没有满足,它会给你其余元素的 undefined

解决方案:

解决方案一: 如果你想在条件满足时返回数组中的整个条目,你可以使用 arr.filter(),这样过滤器将在迭代中返回整个条目,例如,如果你有像下面这样的对象数组

const arr = [{name: "Name1", age: 25}, {name: "Name2", age: 30}, {name: "Name3", age: 25}]

并且当条件满足时,您想返回整个对象,如下例所示

const filteredItems = arr.filter((item)=>{if(item.age === 25){return true}})


console.log(filteredItems) //results: [{name: "Name1", age: 25}, {name: "Name3", age: 25}]

结论: 如果满足条件,则 filter()方法返回包含其中所有项的数组。

解决方案二: 如果只想返回数组中对象(或整个对象或任何形状的数据)的特定数据,也就是说,如果只想返回数组中没有年龄的名称,可以这样做

const namesOnly = arr.map((item)=>{if(item.age === 25){return item.name}})


console.log(namesOnly) //results: ["Name1, udefined, "Name3"]

现在移除 undefined你只需要使用 filter()方法对结果如下

const namesOnly = arr.map((item)=>{if(item.age === 25){return item.name}}).filter((item)=> !!item)


console.log(namesOnly) //results: ["Name1, "Name3"]

结论: ABC0方法在返回值中返回一个特定定义数据的数组,如果不满足该条件,则返回 undefined。这样我们就可以用 ABC2方法去掉 undefined

您可以使用下面的示例代码轻松地使用 .map过滤记录

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);

当希望从原始数组生成新的修改后的数组时,可以使用 Map。 简单的答案可能是某人

      var arr = ['a','b',1];
var results = arr.filter(function(item){
// Modify your original array here
return typeof item ==='string';
}).filter(a => a);