【问题标题】:JS filter doesn't work properly when filtering an array过滤数组时JS过滤器无法正常工作
【发布时间】:2019-11-12 17:31:00
【问题描述】:

在我的 react native 应用程序中,我有以下数组。

export const ID_OPTIONS = [
  { id: 'nric_fin', name: 'NRIC/FIN' },
  { id: 'passport', name: 'Passport' },
  { id: 'birth_cert', name: 'Birth Certificate' },
];

我尝试如下过滤这个数组。

setSelectedIdType = (idType) => {
  return ID_OPTIONS.filter((type) => {
    if (type.id === idType) {
      return type.name;
    }
    return null;
  });
}

但是,这会返回一个对象。我想得到名字作为结果。我在这里做错了什么?

【问题讨论】:

  • 过滤器返回类型用作布尔值来确定当前元素是否应该保留。你希望你的函数做什么?这个名字令人困惑,它没有设置任何东西,只是找到了一些东西。您只想要返回的名称吗?一组名称?

标签: javascript arrays node.js reactjs object


【解决方案1】:

看起来更像是在寻找 for 循环:

setSelectedIdType = (idType) => {
  for (let type of ID_OPTIONS) {
    if (type.id === idType) {
      return type.name;
    }
  }
  return null;
}

可以使用find实现等价:

setSelectedIdType = (idType) => {
  let type = ID_OPTIONS.find(type => type.id === idType);
  return type && type.name;
}

(当找不到 id 时,这将返回 undefined 而不是 null;如有必要,type === undefined ? null : type.name 之类的东西会改变它。)

【讨论】:

    【解决方案2】:

    A filter 过滤数组中的元素......无论您返回的确切内容是什么,返回值都将被简单地视为“真实”或“虚假”(函数返回的元素保留“真实”值,丢弃其他值)。

    所有非空字符串在 Javascript 中都是“真实的”。

    【讨论】:

      【解决方案3】:

      只使用Array.find 而不是Array.filter,因为filter 返回过滤后的数组而不是一项。 Array.find 返回第一个匹配的项目,然后您可以在其上获取 name

      根据Array.filter docs - 返回值

      包含通过测试的元素的新数组。如果没有元素通过 测试,会返回一个空数组。

      关于test 函数,Array.filter 每次迭代都会执行:

      函数是一个谓词,用来测试数组的每个元素。返回 true 保留元素,false 否则。

      注意返回值是boolean

      使用Array.find,您的功能可能只是:

      const ID_OPTIONS = [ { id: 'nric_fin', name: 'NRIC/FIN' }, { id: 'passport', name: 'Passport' }, { id: 'birth_cert', name: 'Birth Certificate' }, ];
      
      let setSelectedIdType = idType => 
        (ID_OPTIONS.find(x => x.id === idType) || {}).name
      
      console.log(setSelectedIdType('nric_fin'))
      console.log(setSelectedIdType('passport'))

      【讨论】:

        【解决方案4】:

        之后只需map 数组即可获得name

        return ID_OPTIONS.filter(...).map(({ name }) => name);
        

        您也可以使用reduce 来降低复杂性:

        setSelectedIdType = idType => ID_OPTIONS.reduce((a, { id, name }) => id == idType ? (a.push(name), a) : a, []);
        

        【讨论】:

          【解决方案5】:

          引用Mozilla Filter Function Docs

          callback 函数是一个谓词,用来测试数组的每个元素。返回 true 以保留元素,否则返回 false。

          Return value 包含通过测试的元素的新数组。如果没有元素通过测试,则返回一个空数组。

          我认为过滤器的回调不能是布尔值 而返回值应该是一个包含过滤器函数匹配结果的数组

          【讨论】:

            【解决方案6】:

            您的域是否有必要将对象存储在数组中?

            由于您已将它们声明为常量,因此我将假设它们不会改变,除非重新加载客户端。

            如果您要将这个对象数组转换为像这样的简单对象:

            const NAMES = ID_OPTIONS.reduce((obj,idOption) => {
              obj[idOption.id] = {name: idOption.name};
              return obj;
            },{});
            

            这将导致:

            {
              nric_fin: {name: 'NRIC/FIN'},
              passport: {name: 'Passport'},
              birth_cert: { name: 'Birth Certificate'}
            }
            

            现在您可以通过属性访问名称

            let idType = 'passport';
            NAMES[idType];
            

            【讨论】:

              猜你喜欢
              • 2013-09-15
              • 1970-01-01
              • 2015-02-14
              • 2013-08-16
              • 2012-11-16
              • 2011-04-06
              相关资源
              最近更新 更多