【问题标题】:JavaScript .map() function returns unexpected output [duplicate]JavaScript .map() 函数返回意外输出
【发布时间】:2025-11-30 18:55:01
【问题描述】:

我尝试使用 .map() 方法从 JavaScript 对象数组生成字符串,代码如下:

var array1 = [{
    "DepartmentId": 155,
    "DepartmentName": "Animation",
    "Selected": true
  },
  {
    "DepartmentId": 156,
    "DepartmentName": "Software Development",
    "Selected": false
  },
  {
    "DepartmentId": 161,
    "DepartmentName": "Testing",
    "Selected": false
  },
  {
    "DepartmentId": 160,
    "DepartmentName": "Account",
    "Selected": true
  }
];

// pass a function to map
const map1 = array1.map(function(e) {
  if (e.Selected == true) return e.DepartmentId;
}).join(',');

console.log(map1);

我的预期输出是:155,160

但它给了我

实际输出为:155,,,160

【问题讨论】:

  • map 返回的元素数量与您提供的完全相同,您可能想使用filter 然后map

标签: javascript


【解决方案1】:

if 不满足时,undefined 从回调中返回,导致加入时数组中的空点。请先使用.filter

var array1 = [{
    "DepartmentId": 155,
    "DepartmentName": "Animation",
    "Selected": true
  },
  {
    "DepartmentId": 156,
    "DepartmentName": "Software Development",
    "Selected": false
  },
  {
    "DepartmentId": 161,
    "DepartmentName": "Testing",
    "Selected": false
  },
  {
    "DepartmentId": 160,
    "DepartmentName": "Account",
    "Selected": true
  }
];

// pass a function to map
const map1 = array1
  .filter(e => e.Selected)
  .map(e => e.DepartmentId)
  .join(',');

console.log(map1);

或者,在一次迭代中 filtermap 使用 reduce 代替:

var array1 = [{
    "DepartmentId": 155,
    "DepartmentName": "Animation",
    "Selected": true
  },
  {
    "DepartmentId": 156,
    "DepartmentName": "Software Development",
    "Selected": false
  },
  {
    "DepartmentId": 161,
    "DepartmentName": "Testing",
    "Selected": false
  },
  {
    "DepartmentId": 160,
    "DepartmentName": "Account",
    "Selected": true
  }
];

// pass a function to map
const map1 = array1
  .reduce((a, e) => {
    if (e.Selected) {
      a.push(e.DepartmentId);
    }
    return a;
  }, [])
  .join(',');

console.log(map1);

【讨论】:

  • 您也可以通过调用.reduce((a,e)=>{if(e.Selected){ if(a!==''){ a+=','; } a+=e.DepartmentId; } return a;}, '') 来组合reducejoin 步骤
【解决方案2】:

如所指出的,通常的方法是先过滤,然后映射。

重复链接中指出的另一个选项是使用 reduce。

但我想我添加另一个选项,你可以map 然后filter 也可以,你可以只做filter(Boolean)

var array1 = [{
    "DepartmentId": 155,
    "DepartmentName": "Animation",
    "Selected": true
  },
  {
    "DepartmentId": 156,
    "DepartmentName": "Software Development",
    "Selected": false
  },
  {
    "DepartmentId": 161,
    "DepartmentName": "Testing",
    "Selected": false
  },
  {
    "DepartmentId": 160,
    "DepartmentName": "Account",
    "Selected": true
  }
];

// pass a function to map
const map1 = array1.map(function(e) {
  if (e.Selected == true) return e.DepartmentId;
}).filter(Boolean).join(',');

console.log(map1);

【讨论】:

  • 此解决方案不会降低复杂性,因为它在最后一步而不是在第一步进行过滤。试想一下,你有一百万个项目,结果集只包含两个,那么你需要迭代这百万个项目两次。而不是用一个竖框过滤,只用两个进行映射。
  • @NinaScholz 是的,我了解filtermap 的工作原理.. :) 就像指出的那样,我只是提供了另一种选择。如果 OP 提到性能是一个关键问题,我可以在这里理解您的评论。
  • 性能始终是关键,即使没有提及。
  • @NinaScholz 关键是它可以工作,这是可以理解的,优化是通常作为次要考虑的事情。但无论如何,让我们以你的 100 万为例。刚刚对一百万条记录进行了基准测试,这是结果。 filter(Boolean) = 83.215msfilter , map = 64.245ms,最后是 flatMap = 175.615ms 这是在 Chrome / Windows 上,当然不同的 JS 引擎在这里可能会给出不同的结果,但我认为这很重要。我知道你在 JS 方面有更多经验,但我多年来学到的一件事是尽量避免预先优化。
【解决方案3】:

您需要先过滤,然后再映射想要的属性。

var array1 = [{ DepartmentId: 155, DepartmentName: "Animation", Selected: true }, { DepartmentId: 156, DepartmentName: "Software Development", Selected: false }, { DepartmentId: 161, DepartmentName: "Testing", Selected: false }, { DepartmentId: 160, DepartmentName: "Account", Selected: true }];

const map1 = array1
    .filter(({ Selected }) => Selected)
    .map(({ DepartmentId }) => DepartmentId)
    .join(',');

console.log(map1);

单函数,需要取flatMap

var array1 = [{ DepartmentId: 155, DepartmentName: "Animation", Selected: true }, { DepartmentId: 156, DepartmentName: "Software Development", Selected: false }, { DepartmentId: 161, DepartmentName: "Testing", Selected: false }, { DepartmentId: 160, DepartmentName: "Account", Selected: true }];

const map1 = array1
    .flatMap(({ Selected, DepartmentId  }) => Selected ? DepartmentId : [])
    .join(',');

console.log(map1);

【讨论】:

    【解决方案4】:

    一个选项是使用reduce。这将遍历每个数组元素,并且只包含Selected 数组元素的部门 ID

    var array1 = [{
        "DepartmentId": 155,
        "DepartmentName": "Animation",
        "Selected": true
      },
      {
        "DepartmentId": 156,
        "DepartmentName": "Software Development",
        "Selected": false
      },
      {
        "DepartmentId": 161,
        "DepartmentName": "Testing",
        "Selected": false
      },
      {
        "DepartmentId": 160,
        "DepartmentName": "Account",
        "Selected": true
      }
    ];
    
    // pass a function to map
    const map1 = array1.reduce(function(c, e) {
      if (e.Selected == true) return c.concat(e.DepartmentId);
      else return c;
    }, []).join(',');
    
    console.log(map1);

    短版:

    var array1 = [{"DepartmentId":155,"DepartmentName":"Animation","Selected":true},{"DepartmentId":156,"DepartmentName":"Software Development","Selected":false},{"DepartmentId":161,"DepartmentName":"Testing","Selected":false},{"DepartmentId":160,"DepartmentName":"Account","Selected":true}]
    
    const map1 = array1.reduce((c, e) => e.Selected ? c.concat(e.DepartmentId) : c, []).join(',');
    
    console.log(map1);

    【讨论】:

      【解决方案5】:

      结合使用map和filter来实现这个

      var array1 = [
              {
                  "DepartmentId": 155,
                  "DepartmentName": "Animation",
                 	"Selected":true
              },
              {
                  "DepartmentId": 156,
                  "DepartmentName": "Software Development",
                  "Selected":false
              },
              {
                  "DepartmentId": 161,
                  "DepartmentName": "Testing",
                  "Selected":false
              },
              {
                  "DepartmentId": 160,
                  "DepartmentName": "Account",
                  "Selected":true
              }       
          ];
      
      // pass a function to map
      const map1 = array1.filter(function(e){
      return e.Selected;
      }).map(function(x){return x.DepartmentId}).join(',');
      
      console.log(map1);

      【讨论】: