【问题标题】:Javascript find object with matching property in array of objects and get another property if existsJavascript在对象数组中查找具有匹配属性的对象,如果存在则获取另一个属性
【发布时间】:2019-01-20 22:15:34
【问题描述】:

我正在为以下问题寻找一个优雅的解决方案:

在我的代码的许多地方,我需要在对象数组中找到一个与 id 匹配的对象,然后返回该对象的属性。引用的 id可能存在也可能不存在在数组中。

我想出的最短解决方案如下:

(如果项目存在则想获取项目的标题,否则不返回)

arrayofObjects = [ { id: 'a3ff3d', title: 'Tesla', color: 'Red' }, { id: 'r43wesd', title: 'AMC', color: 'Rust' }]
wantedObject = { queryTitle: 'Desired Car', id: 'a3ff3d' }


let wantedProperty = arrayOfObjects.some( e => e.id === wantedObject.id) ? arrayOfObjects.find(e => e.id === wantedObject.id).title : 'None Found'

但是,这既不优雅也不高效。我更喜欢它是一个单行而不是一个函数。

【问题讨论】:

  • 您应该提供一些示例数据和预期结果。您应该能够使用一次find,而不是some + find。它应该返回一个有用的值,例如 undefinednull 其他进程可以使用,而不是随机字符串。
  • “单线”和“高效”很多时候并没有真正齐头并进。与Array.prototype 方法相比,普通的for 循环总是会获得更高的性能。
  • (array.find(…) || {}).title
  • 添加了示例数据。是的,我在想我应该能够使用一次 find ,但我正在努力编写它。返回 undefined 或 null 是可以接受的。
  • @PatrickRoberts 不正确,原生数组方法是 just as fast 作为 for 循环。

标签: javascript arrays performance


【解决方案1】:

最小的方法不一定是最有效的。我会这样做:

let wantedProperty = (arrayOfObjects.find(obj => obj.id === wantedObject.id) || {}).title || 'None Found';

【讨论】:

  • 我认为如果您将 e 替换为更有意义的变量名称,例如 obj 或类似名称,它会更清晰,例如obj.id == wantedObj.id。 :-)
  • 感谢大家的建议! Bergi 实际上提出了这种确切的方法作为对原始问题的评论,我喜欢它。接受它作为答案。
【解决方案2】:

使用 Array#find 和解构。

const data = [ { id: 'a3ff3d', title: 'Tesla', color: 'Red' }, { id: 'r43wesd', title: 'AMC', color: 'Rust' }];

function search(idToFind){
  const res = data.find(({id}) => id === idToFind);
  return res ? res.title : "Nothing found";
}


console.log(search('r43wesd'));
console.log(search('fail'));

【讨论】:

    【解决方案3】:

    实际上,您可以为您的数据结构创建一个可以重复使用多次的单行通用方法:

    const arrayOfObjects = [
        {id: 'a3ff3d', title: 'Tesla', color: 'Red'},
        {id: 'r43wesd', title: 'AMC', color: 'Rust'}
    ];
    
    const getKey = (a, id, key) => (f = a.find(x => x.id === id)) ? f[[key]] : "Not Found";
    
    console.log(getKey(arrayOfObjects, "a3ff3d", "title"));
    console.log(getKey(arrayOfObjects, "r43wesd", "color"));
    console.log(getKey(arrayOfObjects, "someid", "color"));

    【讨论】:

      【解决方案4】:

      我想到了两种可能的解决方案。第一个我不推荐:

      array.reduce((acc, cur) => {
          return cur.id == searchedId ? cur.title : acc;
      }, "None found");
      

      特别是如果你需要经常使用它,避免“复杂”的代码,即使我们正在考虑一行。

      第二个选项(如果你真的不想使用函数)是这个:

      Array.prototype.findOrElse = function(cb, objcb, retValue) {
          let findElem = this.find(elem => cb(elem));
      
          return objcb(findElem) || retValue;
      }
      

      你可以这样称呼它:

      array.findOrElse(elem => elem.id == searchedId, elem => elem.title, "None found");
      

      一般我不会选择这种方式,因为我不喜欢接触js提供的原生对象,但没有人禁止。


      编辑: 正如@PatrickRoberts 让我注意到的那样,这并不是真正的答案。我刚刚发现了 2 个可能的解决方案,出于不同的原因我不推荐。函数有这个优点:你不必重复相同的代码,即使它是一行。考虑一种可能的情况,您可能必须检索不同的属性而不是title

      另一方面,在Array 对象的原型中自定义一个函数是困难的:你试图使该函数尽可能通用,但存在函数定义过于复杂的风险。

      那么为什么不使用你自己定义的函数呢?

      【讨论】:

      • 我发现第二个建议非常复杂。不过,这不是我的反对意见。
      • 我不相信elem.id == {searchedId} 也不会评估为true
      • @RobG 我同意并指定我不使用它。它很复杂,但很灵活,如果他不喜欢使用函数,第二个选项比多次使用相同的复杂代码段更好。
      • 您的意思是elem.id == searchedIdcur.id == {searchedId} 也一样,你的意思可能是 cur.id == searchedId
      • @PatrickRoberts — 我认为这是一个有效的答案,只是我不会投票。 :-)
      猜你喜欢
      • 2022-11-21
      • 2020-04-09
      • 1970-01-01
      • 2020-06-09
      • 2020-06-20
      • 2019-04-14
      • 2022-09-23
      • 2019-07-14
      • 1970-01-01
      相关资源
      最近更新 更多