简体   繁体   English

为什么 JavaScript map function 返回未定义?

[英]Why does JavaScript map function return undefined?

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.我不想在结果数组中undefined How can I do it?我该怎么做?

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.在这种情况下,该函数返回undefined ,即您在结果中看到的内容。

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. map 函数用于将一个值映射到另一个值,但看起来您实际上想要过滤数组,而 map 函数不适合这种情况。

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.它需要一个函数,根据您是否想要结果数组中的项目返回 true 或 false。

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.但是在很多情况下,当您使用 map 时,您希望对传递的项目进行一些修改。

if that is your intent, you can use reduce :如果这是您的意图,您可以使用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
}, [])

Since ES6 filter supports pointy arrow notation (like LINQ):由于 ES6 filter支持尖箭头符号(如 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.这应该支持每种 JS 数据类型。

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

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

You only return a value if the current element is a string .如果当前元素是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() .当然,如果要过滤任何非字符串元素,则不应使用map() Rather, you should look into using the filter() function.相反,您应该考虑使用filter()函数。

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

If you have to use map to return custom output, you can still combine it with filter.如果您必须使用 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']

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...使用 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;}
    }
);

I run into this quite frequently where the type after filtering will still be string | number我经常遇到这种情况,过滤后的类型仍然是string | number string | number . 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 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, ie 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 eg 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.问题:问题是arr.map()将对arr数组长度进行完整迭代,即map()方法将循环arr的长度,无论你在其中有什么条件,所以如果你定义其中的一个条件,例如if(typeof item ==='string'){return item;}即使条件没有发生, map()也会被迫继续循环,直到完成整个arr的循环,所以它会如果不满足条件,则为元素的 rest 提供undefined

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 eg if you have array of objects like bellow解决方案一:如果你想在满足条件时返回数组中的整个项目,你可以使用arr.filter()这样过滤器将返回整个项目进行迭代,例如,如果你有像波纹管这样的对象数组

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.结论:如果满足条件, filter()方法将返回其中所有项目的数组。

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 ie if you want to return only the names in array without the ages, you can do this解决方案二:如果您只想返回数组中对象的特定数据(或整个 object 或任何形状的数据),即如果您只想返回数组中的名称而不返回年龄,您可以这样做

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现在要删除undefined的,您只需对结果使用filter()方法,如下所示

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.结论: map()方法在return中返回一个具体定义数据的数组,不满足条件则返回undefined so then we can use filter() method to remove the undefined .那么我们就可以使用filter()方法来删除undefined

You can filter records with .map easily using below example code您可以使用以下示例代码轻松地使用.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 is used when you want to produced new modified array from the original array. Map 用于从原始数组生成新的修改后的数组。 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM