【问题标题】:How to map items without undefined value in javascript with Array.prototype.map and without Array.prototype.filter()如何使用 Array.prototype.map 和没有 Array.prototype.filter() 在 javascript 中映射没有未定义值的项目
【发布时间】:2019-07-02 19:41:26
【问题描述】:

如何使用 Array.prototype.map 和不使用 Array.prototype.filter() 在 javascript 中映射没有未定义值的项目

代码:

var testArray = [
  {
    name: "toto",
    totoNumber: "1",
  },
  {
    name: "tata",
    totoNumber: "2",
  },
  {
    mame: "error",
  },
]

var listOfToto = testArray.map(x => x.totoNumber);
var listOfToto2 = testArray.map(x => x.totoNumber ? x.totoNumber : undefined);
var listOfToto3 = testArray.filter(x => x.totoNumber).map(x => x.totoNumber);

console.log(listOfToto);  
console.log(listOfToto2);  
console.log(listOfToto3);  

价值观:

数组 ["1", "2", 未定义]
数组 ["1", "2", 未定义]
数组 ["1", "2"]

我想在不使用 Array.prototype.filter()
的情况下获取最后一个数组 (["1", "2"]) (也许除了 Array.prototype.map() 之外的其他东西)

其他来源:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Why does javascript map function return undefined?
https://codewithhugo.com/avoiding-falsy-values-in-javascript-arrays/

【问题讨论】:

  • "不使用 Array.prototype.filter()" - 但是...这就是 array.filter() 的全部目的。我认为您担心您正在使用两个循环(filter,然后是map)。不要这样。
  • 您可以使用reduce 来构建您的新数组,并且只在需要时才包含元素,但是使用mapfilter 会更容易阅读和维护跨度>
  • 另外,过滤其他方式更容易并且避免代码重复:testArray.map(x => x.totoNumber).filter(e => e)(尽管如果您可以将零作为值,您可能需要显式检查!== undefined
  • 问题是我不应该有来自后端的未定义值,我不想在任何地方添加 .filter 以确保我不会遇到与今天相同的错误。我希望有一个 .map2

标签: javascript arrays array.prototype.map


【解决方案1】:

您可以使用reduce

let data = testArray.reduce((result, item) => item.totoNumber ? result.concat(item.totoNumber) : result, []);

// Or a slightly more efficient solution
// if you are worried about concat creating a new temporary array at each iteration

let data = testArray.reduce((result, item) => {
    if (item.totoNumber) {
        result.push(item.totoNumber);
    }
    return result;
}, []);

但你为什么要避开filter?它使代码更具可读性(在我看来),除非您正在处理一个巨大的数组或在一个对时间非常敏感的函数中工作,否则这将是一个您不应该牺牲清晰度的微优化。

在我看来,这看起来更干净:

let data = testArray.map(item => item.totoNumber).filter(e => e);

【讨论】:

  • 问题是我不应该有来自后端的未定义值,我不想在任何地方添加 .filter 以确保我不会遇到与今天相同的错误。我希望能找到类似 .map2 的东西。
  • 我的意思是你能做到。 Array.prototype.map2 = function() { return this.map(...arguments).filter(e => e); }(你很可能不应该,只要找到未定义值的来源并确保在那里处理它)
【解决方案2】:

如果值不存在,您可以使用Array.flatMap() 并返回一个空数组[]

const testArray = [{"name":"toto","totoNumber":"1"},{"name":"tata","totoNumber":"2"},{"mame":"error"}]

const listOfToto2 = testArray.flatMap(x => x.totoNumber ? x.totoNumber : []);

console.log(listOfToto2);  

【讨论】:

  • 这将是一个解决方案,但它不是 flatMap 的主要用途。在这种情况下,我会保留 .filter 和 .map
  • 是的,我愿意。这只是对“我可以……”问题的回答。
【解决方案3】:

您可以考虑以下几个选项,所有这些选项都需要一个循环。

var arr = [ { name: "toto", totoNumber: "1", }, { name: "tata", totoNumber: "2", }, { mame: "error", }, ]

// via Array.forEach
let fe = []
arr.forEach(({totoNumber}) => totoNumber ? fe.push(totoNumber) : 0)

// via Array.reduce
let r = arr.reduce((acc,{totoNumber}) => (totoNumber ? acc.push(totoNumber) : 0, acc), [])

// via Array.map acting like Array.forEach 
let m = []
arr.map(({totoNumber}) => (totoNumber ? m.push(totoNumber) : 0, totoNumber))

console.log(fe)
console.log(r)
console.log(m)

实际上只有Array.reduce 才有意义,处理您的场景的常用方法是通过Array.filter 然后Array.map 但既然您问是否可以仅使用map...但是map 应该返回完全相同的数组长度,所以它真的不是最合适的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-13
    • 2019-12-23
    • 2019-04-19
    相关资源
    最近更新 更多