【问题标题】:Find object by id in an array of JavaScript objects在 JavaScript 对象数组中通过 id 查找对象
【发布时间】:2022-11-10 14:32:16
【问题描述】:

我有一个数组:

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}, etc.]

我无法更改数组的结构。我被传递了一个 45 的 ID,我想为数组中的那个对象获取 'bar'

我如何在 JavaScript 或使用 jQuery 中执行此操作?

【问题讨论】:

    标签: javascript arrays javascript-objects


    【解决方案1】:

    使用 find() 方法:

    myArray.find(x => x.id === '45').foo;
    

    来自MDN

    find() 方法返回数组中的第一个值,如果数组中的元素满足提供的测试函数。否则返回undefined


    如果你想找到它指数相反,使用findIndex()

    myArray.findIndex(x => x.id === '45');
    

    来自MDN

    findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回 -1。


    如果要获取匹配元素的数组,请改用 filter() 方法:

    myArray.filter(x => x.id === '45');
    

    这将返回一个对象数组。如果你想获得一组foo属性,你可以使用map()方法来实现:

    myArray.filter(x => x.id === '45').map(x => x.foo);
    

    旁注:像find()filter()arrow functions这样的方法不受旧浏览器(如IE)的支持,所以如果你想支持这些浏览器,你应该使用Babel(带有@ 987654327@)。

    【讨论】:

    • 因此,对于多个测试条件,它会是这样的:myArray.find(x => x.id === '45' && x.color == 'red').foo
    • 对我来说,到目前为止最好的答案。不需要 jQuery,也不需要创建新的辅助数组。
    • filter居然已经支持回IE9了!
    • myArray.find(x => x.id === '45').foo;如果不存在 ID 为“45”的对象,则抛出异常。
    • 我可以在 find 方法中添加多个条件吗?
    【解决方案2】:

    由于您已经在使用 jQuery,因此可以使用用于搜索数组的 grep 函数:

    var result = $.grep(myArray, function(e){ return e.id == id; });
    

    结果是一个包含找到的项目的数组。如果您知道该对象始终存在并且只出现一次,则只需使用result[0].foo 即可获取该值。否则你应该检查结果数组的长度。例子:

    if (result.length === 0) {
      // no result found
    } else if (result.length === 1) {
      // property found, access the foo property using result[0].foo
    } else {
      // multiple items found
    }
    

    【讨论】:

    • 使用 === 而不是 == 会更安全,以避免 JavaScript 的 == 运算符出现奇怪的问题。
    • @VickyChijwani:将字符串与字符串进行比较时有什么问题吗?
    • 好吧,如果你是绝对地确保e.idid都是字符串,我想可以使用==。但如果您不确定,您可能会遇到问题(因为 '' == 0true'' === 0false)。更不用说=== 似乎更快(stackoverflow.com/questions/359494/…)。
    • 基本上我总是使用=== 因为它有效确切地就像其他编程语言中的==。我认为 == 在 JavaScript 中不存在。
    • @德。这里的许多答案都提供了查找唯一值时的预期行为;您基本上可以通过它们提前返回或从循环中中断(或指示较低级别的构造停止迭代)这一事实来识别它们。有关典型示例,请参阅 JaredPar 的回答,对于相同的见解,请参阅 Aaronius 对该答案的评论。通常,人们以这种方式区分“筛选”和“查找”功能,但术语各不相同。虽然效率更高,但这仍然是线性搜索,因此如果您想使用哈希表,请参阅 Aaron Digulla 的回答(注意 impl. details)。
    【解决方案3】:

    另一种解决方案是创建一个查找对象:

    var lookup = {};
    for (var i = 0, len = array.length; i < len; i++) {
        lookup[array[i].id] = array[i];
    }
    
    ... now you can use lookup[id]...
    

    如果您需要进行多次查找,这将特别有趣。

    这不需要更多内存,因为 ID 和对象将被共享。

    【讨论】:

    • 正是我要找的。有趣的是,当我只需要改变从 CouchDB 接收到的数据并将其转换为对我有用的格式时,我试图通过每次循环遍历,从列表中删除每一项来使它过于复杂,这很有趣需要。 +1 先生!
    • 这很聪明。我无法想象其他人是如何通过在每次使用时查看整个阵列而被说服的。
    • 只要你不依赖属性的顺序:stackoverflow.com/questions/4886314/…
    • 正在休息;如果您知道只有一个对象可以找到,那么在循环中是一个不错的选择/改进吗?
    • @irJvV:不,那根本没有意义。如果您需要进行多次查找,上面的代码很有用。如果只看一次,那么创建 lookup 对象就是浪费时间。
    【解决方案4】:

    ECMA 脚本 2015(JavaScript ES6) 提供find() 数组方法:

    var myArray = [
     {id:1, name:"bob"},
     {id:2, name:"dan"},
     {id:3, name:"barb"},
    ]
    
    // grab the Array item which matchs the id "2"
    var item = myArray.find(item => item.id === 2);
    
    // print
    console.log(item.name);

    它在没有外部库的情况下工作。但是如果你想要older browser support,你可能想要包括this polyfill

    【讨论】:

    • 可能是因为它看起来仍然很实验性,并且没有多少浏览器支持它,developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    • 这可以简化为myArray.find(d=&gt;d.id===45).foo;
    • @Shaggy 甚至myArray.find(({ id }) =&gt; id === 45).foo。但这是在 ES2015 语法得到像现在这样的支持之前编写的旧答案。 @Gothdo 的answer 是目前最新的话题。
    • @Shaggy 如果 .find() 返回未定义,那么您的优化会抛出错误。所以这个解决方案只能在保证匹配的情况下使用。
    • @HerbertPeters 如果你想确保你总是可以进行空值检查,optional chainingmyArray.find(d =&gt; d.id === 45)?.foo 将非常容易。
    【解决方案5】:

    Underscore.js 有一个很好的方法:

    myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'},etc.]
    obj = _.find(myArray, function(obj) { return obj.id == '45' })
    

    【讨论】:

    • 郑重声明,Lo-Dash(通常明显比 Underscore 性能更高)也有类似的方法。文档在这里:lodash.com/docs#find
    • 如果您只期望一个对象,那么使用 findWhere 会更有效,因为在找到一个结果后,搜索将不会继续进行。
    • @Foreever 来自 _.find 的文档:“该函数在找到可接受的元素后立即返回,并且不会遍历整个列表。”
    【解决方案6】:

    我认为最简单的方法如下,但它不适用于 Internet Explorer 8(或更早版本):

    var result = myArray.filter(function(v) {
        return v.id === '45'; // Filter out the appropriate one
    })[0].foo; // Get result and access the foo property
    

    【讨论】:

    • 我很好奇,与通常的for相比,这里有什么性能优势吗?
    • @Igor Zinov'yev:是的,这些 ES5 阵列工具肯定会对性能产生影响。为每个元素执行一个单独的函数,因此与直接的 for 循环相比,它不会很快。
    • 所以你是说它会更慢?此外,据我所知,它将始终扫描整个数组,而 for 循环将在第一次匹配时终止。
    • 如果您需要对 IE8 的支持,只需将其放入:stackoverflow.com/questions/7153470/…
    • 如果 id 没有元素,此代码将抛出错误
    【解决方案7】:

    尝试以下

    function findById(source, id) {
      for (var i = 0; i < source.length; i++) {
        if (source[i].id === id) {
          return source[i];
        }
      }
      throw "Couldn't find object with id: " + id;
    }
    

    【讨论】:

    • 这不值得自己回答,但在现代浏览器中,这个解决方案可以写成:jsfiddle.net/rwaldron/j3vST
    • 如果你想提高效率,请注意这个例子可能比使用 filter() 更快(参见 Rick 的例子),因为这个例子一旦找到第一个匹配项就会返回,而 filter() 即使在找到第一个匹配项之后也会继续运行整个数组匹配。这也没有创建额外数组或为每个项目调用函数的成本。
    • @Rick,这个答案最有趣的地方显然是您可以将 firebug 控制台添加到 jsFiddle 的输出窗口中。这比登录并告诉其他人打开控制台查看输出要好得多。惊人的!
    • 由于到目前为止还没有人提到它,我想补充一点,AngularJS 也有一个 filter 方法。
    【解决方案8】:
    myArray.filter(function(a){ return a.id == some_id_you_want })[0]
    

    【讨论】:

    【解决方案9】:

    上面的 findById 函数的通用且更灵活的版本:

    // array = [{key:value},{key:value}]
    function objectFindByKey(array, key, value) {
        for (var i = 0; i < array.length; i++) {
            if (array[i][key] === value) {
                return array[i];
            }
        }
        return null;
    }
    
    var array = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
    var result_obj = objectFindByKey(array, 'id', '45');
    

    【讨论】:

      【解决方案10】:

      表现

      今天 2020.06.20 我针对所选解决方案在 Chrome 81.0、Firefox 77.0 和 Safari 13.1 上对 MacOs High Sierra 进行了测试。

      使用预先计算的解决方案的结论

      具有预先计算 (K,L) 的解决方案比其他解决方案(快得多)并且不会与它们进行比较 - 可能它们使用了一些特殊的内置浏览器优化

      • 令人惊讶的是,基于Map (K) 的 Chrome 和 Safari 解决方案比基于对象 {} (L) 的解决方案快得多
      • 令人惊讶的是,基于对象{}(L)的小型数组解决方案在 Safari 上比传统的for(E)慢
      • 令人惊讶的是,基于Map (K) 的小型阵列解决方案在 Firefox 上比传统的 for (E) 慢

      搜索对象始终存在时的结论

      • 使用传统for (E) 的解决方案对小阵列最快,对大阵列也最快
      • 使用高速缓存 (J) 的解决方案对于大阵列来说是最快的 - 令人惊讶的是对于小阵列来说速度中等
      • 基于find (A) 和findIndex (B) 的解决方案对于小阵列来说速度很快,在大阵列上速度中等
      • 基于$.map (H) 的解决方案在小型阵列上最慢
      • 基于reduce (D) 的解决方案在大阵列上最慢

      搜索到的对象从不存在时的结论

      • 基于传统for (E) 的解决方案在小型和大型阵列上最快(Chrome 小型阵列除外,它第二快)
      • 基于reduce (D) 的解决方案在大阵列上最慢
      • 使用缓存 (J) 的解决方案速度中等,但如果我们将具有空值的键也保存在缓存中,则可以加快速度(这里没有这样做,因为我们想避免缓存中的无限内存消耗,以防许多不存在的情况)将搜索现有密钥)

      细节

      对于解决方案

      • 没有预先计算:A B C D E F G H I J(J 解决方案使用“内部”缓存,它的速度取决于搜索元素重复的频率)
      • 预先计算 K L

      我进行了四项测试。在测试中,我想在 10 次循环迭代中找到 5 个对象(对象 ID 在迭代期间不会改变) - 所以我调用测试方法 50 次,但只有前 5 次具有唯一的 id 值:

      • 小数组(10 个元素)和搜索对象始终存在 - 你可以执行它HERE
      • 大数组(10k 元素)和搜索对象始终存在 - 你可以执行它HERE
      • 小数组(10 个元素)和搜索对象从不存在 - 你可以执行它HERE
      • 大数组(10k 元素)和搜索对象从不存在 - 你可以执行它HERE

      测试代码如下

      function A(arr, id) {
        return arr.find(o=> o.id==id);
      }
      
      function B(arr, id) {
        let idx= arr.findIndex(o=> o.id==id);
        return arr[idx];
      }
      
      function C(arr, id) {
        return arr.filter(o=> o.id==id)[0];
      }
      
      function D(arr, id) {
        return arr.reduce((a, b) => (a.id==id && a) || (b.id == id && b));
      }
      
      function E(arr, id) {
        for (var i = 0; i < arr.length; i++) if (arr[i].id==id) return arr[i];
        return null;
      }
      
      function F(arr, id) {
        var retObj ={};
        $.each(arr, (index, obj) => {
          if (obj.id == id) { 
            retObj = obj;
            return false;
          }
        });
        return retObj;
      }
      
      function G(arr, id) {
        return $.grep(arr, e=> e.id == id )[0];
      }
      
      function H(arr, id) {
        return $.map(myArray, function(val) {
          return val.id == id ? val : null;
        })[0];
      }
      
      function I(arr, id) {
        return _.find(arr, o => o.id==id);
      }
      
      let J = (()=>{
        let cache = new Map();
        return function J(arr,id,el=null) { 
          return cache.get(id) || (el=arr.find(o=> o.id==id), cache.set(id,el), el);
        }
      })();
      
      function K(arr, id) {
        return mapK.get(id)
      }
      
      function L(arr, id) {
        return mapL[id];
      }
      
      
      
      // -------------
      // TEST
      // -------------
      
      console.log('Find id=5');
      
      myArray = [...Array(10)].map((x,i)=> ({'id':`${i}`, 'foo':`bar_${i}`}));
      const mapK = new Map( myArray.map(el => [el.id, el]) );
      const mapL = {}; myArray.forEach(el => mapL[el.id]=el);
      
      
      
      [A,B,C,D,E,F,G,H,I,J,K,L].forEach(f=> console.log(`${f.name}: ${JSON.stringify(f(myArray, '5'))}`));
      
      console.log('Whole array',JSON.stringify(myArray));
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
      
      This snippet only presents tested codes

      Chrome 的小型数组示例测试结果,其中搜索对象始终存在

      【讨论】:

      • 这应该是正确答案。当谈到循环时,性能应该是一个重要的标准。
      【解决方案11】:

      正如其他人指出的那样,.find() 是在数组中查找一个对象时的方法。但是,如果使用此方法无法找到您的对象,您的程序将崩溃:

      const myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
      const res = myArray.find(x => x.id === '100').foo; // Uh oh!
      /*
      Error:
      "Uncaught TypeError: Cannot read property 'foo' of undefined"
      or in newer chrome versions:
      Uncaught TypeError: Cannot read properties of undefined (reading 'foo')
      */

      这可以通过在使用 .foo 之前检查是否定义了 .find() 的结果来解决。现代 JS 允许我们使用 optional chaining 轻松完成此操作,如果找不到对象则返回 undefined,而不是让代码崩溃:

      const myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
      const res = myArray.find(x => x.id === '100')?.foo; // No error!
      console.log(res); // undefined when the object cannot be found

      【讨论】:

        【解决方案12】:

        如果多次执行此操作,则可以设置一个 Map (ES6):

        const map = new Map( myArray.map(el => [el.id, el]) );
        

        然后你可以简单地做一个 O(1) 查找:

        map.get(27).foo
        

        【讨论】:

          【解决方案13】:

          您可以使用 map() 函数轻松获得:

          myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
          
          var found = $.map(myArray, function(val) {
              return val.id == 45 ? val.foo : null;
          });
          
          //found[0] == "bar";
          

          工作示例:http://jsfiddle.net/hunter/Pxaua/

          【讨论】:

          • 我忘记了 jQuery 的 map 会自动删除 null 元素这一事实。这听起来误导了我和map 的共同概念,因为结果与原始集合的长度不同。
          【解决方案14】:

          使用本机Array.reduce

          var array = [ {'id':'73' ,'foo':'bar'} , {'id':'45' ,'foo':'bar'} , ];
          var id = 73;
          
          var found = array.reduce(function(a, b){
              return (a.id==id && a) || (b.id == id && b)
          });
          

          如果找到则返回对象元素,否则返回false

          【讨论】:

          • 请注意,IE8 及以下版本不支持 Array.reduce。
          【解决方案15】:

          你可以使用过滤器,

            function getById(id, myArray) {
              return myArray.filter(function(obj) {
                if(obj.id == id) {
                  return obj 
                }
              })[0]
            }
          
          get_my_obj = getById(73, myArray);
          

          【讨论】:

          • @TobiasBeuving - 使用 Array.find() 的也是纯 JS,应该在第一次找到时停止,这样会更有效率。
          【解决方案16】:

          虽然这里有许多正确的答案,但其中许多都没有解决这样一个事实,即如果多次执行此操作,将是不必要的昂贵操作。在极端情况下,这可能是实际性能问题的原因。

          在现实世界中,如果您正在处理大量项目并且性能是一个问题,那么最初构建查找会更快:

          var items = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
          
          var lookup = items.reduce((o,i)=>o[i.id]=o,{});
          

          然后你可以像这样在固定时间获得物品:

          var bar = o[id];
          

          您也可以考虑使用 Map 而不是对象作为查找:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map

          【讨论】:

            【解决方案17】:

            最近,我不得不面对同样的事情,我需要从一个巨大的数组中搜索字符串。

            经过一番搜索,我发现用简单的代码就很容易处理:

            代码:

            var items = mydata.filter(function(item){
                return item.word.toLowerCase().startsWith( 'gk );
            })
            

            https://jsfiddle.net/maheshwaghmare/cfx3p40v/4/

            【讨论】:

              【解决方案18】:

              您可以从 http://sugarjs.com/ 试用 Sugarjs。

              它在数组上有一个非常棒的方法,.find。所以你可以找到这样的元素:

              array.find( {id: 75} );
              

              您还可以将具有更多属性的对象传递给它以添加另一个“where-clause”。

              请注意,Sugarjs 扩展了本机对象,有些人认为这非常邪恶......

              【讨论】:

              • 嗯,它evil,因为新的 EcmaScript 版本可能会引入同名的新方法。你猜怎么着,这是exactly what happened with find。我的建议是,如果您想扩展原生原型,请始终使用更具体的名称,将最简单的名称留给未来的标准开发。
              • 这条评论已经有将近 2 年的历史了,今天我还是宁愿使用 lodash。但是,如果您愿意,可以在 sugarjs 网站上阅读有关此主题的信息。他们对你的意见有很好的立场:sugarjs.com/native
              • 该操作确实特别要求使用 javascript 或 jquery 解决方案
              【解决方案19】:

              遍历数组中的任何项目。对于您访问的每个项目,请检查该项目的 ID。如果匹配,则将其返回。

              如果您只想要法典:

              function getId(array, id) {
                  for (var i = 0, len = array.length; i < len; i++) {
                      if (array[i].id === id) {
                          return array[i];
                      }
                  }
                  return null; // Nothing found
              }
              

              同样的事情使用 ECMAScript 5 的 Array 方法:

              function getId(array, id) {
                  var obj = array.filter(function (val) {
                      return val.id === id;
                  });
              
                  // Filter returns an array, and we just want the matching item.
                  return obj[0];
              }
              

              【讨论】:

                【解决方案20】:

                只要浏览器支持ECMA-262,第 5 版(2009 年 12 月),这应该可以工作,几乎是一行:

                var bFound = myArray.some(function (obj) {
                    return obj.id === 45;
                });
                

                【讨论】:

                • 几乎。 bFound 只是一个布尔值,即 true 当且仅当元素满足所需条件。
                【解决方案21】:

                下面是我在纯 JavaScript 中的处理方式,以我能想到的在 ECMAScript 3 或更高版本中工作的最小方式。一旦找到匹配项,它就会返回。

                var getKeyValueById = function(array, key, id) {
                    var testArray = array.slice(), test;
                    while(test = testArray.pop()) {
                        if (test.id === id) {
                            return test[key];
                        }
                    }
                    // return undefined if no matching id is found in array
                    return;
                }
                
                var myArray = [{'id':'73', 'foo':'bar'}, {'id':'45', 'foo':'bar'}]
                var result = getKeyValueById(myArray, 'foo', '45');
                
                // result is 'bar', obtained from object with id of '45'
                

                【讨论】:

                  【解决方案22】:

                  更通用和简短

                  function findFromArray(array,key,value) {
                          return array.filter(function (element) {
                              return element[key] == value;
                          }).shift();
                  }
                  

                  在你的情况下var element = findFromArray(myArray,'id',45) 将为您提供完整的元素。

                  【讨论】:

                    【解决方案23】:

                    我们可以使用 Jquery 方法$.each()/$.grep()

                    var data= [];
                    $.each(array,function(i){if(n !== 5 && i > 4){data.push(item)}}
                    

                    或者

                    var data = $.grep(array, function( n, i ) {
                      return ( n !== 5 && i > 4 );
                    });
                    

                    使用 ES6 语法:

                    Array.find, Array.filter, Array.forEach, Array.map
                    

                    或者使用 Lodash https://lodash.com/docs/4.17.10#filter, Underscore https://underscorejs.org/#filter

                    【讨论】:

                      【解决方案24】:

                      基于已接受的答案:

                      查询:

                      var foo = $.grep(myArray, function(e){ return e.id === foo_id})
                      myArray.pop(foo)
                      

                      或咖啡脚本:

                      foo = $.grep myArray, (e) -> e.id == foo_id
                      myArray.pop foo
                      

                      【讨论】:

                        【解决方案25】:

                        使用Array.prototype.filter()函数。

                        演示: https://jsfiddle.net/sumitridhal/r0cz0w5o/4/

                        JSON

                        var jsonObj =[
                         {
                          "name": "Me",
                          "info": {
                           "age": "15",
                           "favColor": "Green",
                           "pets": true
                          }
                         },
                         {
                          "name": "Alex",
                          "info": {
                           "age": "16",
                           "favColor": "orange",
                           "pets": false
                          }
                         },
                        {
                          "name": "Kyle",
                          "info": {
                           "age": "15",
                           "favColor": "Blue",
                           "pets": false
                          }
                         }
                        ];
                        

                        筛选

                        var getPerson = function(name){
                            return jsonObj.filter(function(obj) {
                              return obj.name === name;
                            });
                        }
                        

                        【讨论】:

                        • 如何在嵌套对象中搜索?像 pets=false 应该返回两个对象。
                        • 在嵌套循环中对obj.info使用.filter方法。 var getPerson = function(name){ return jsonObj.filter(function(obj) { return obj.info.filter(function(info) { return pets === false; }); }); }
                        • 你也可以使用 es6 样式 imo ... const filterData = jsonObj.filter(obj => obj.name === 'Alex')
                        【解决方案26】:

                        您甚至可以在纯 JavaScript 中使用数组的内置“过滤器”函数来执行此操作:

                        Array.prototype.filterObjects = function(key, value) {
                            return this.filter(function(x) { return x[key] === value; })
                        }
                        

                        所以现在只需传递“id”代替key,传递“45”代替value,您将获得与 id 为 45 匹配的完整对象。那就是,

                        myArr.filterObjects("id", "45");
                        

                        【讨论】:

                        • 不要修改不属于您的对象。
                        【解决方案27】:

                        我真的很喜欢 Aaron Digulla 提供的答案,但需要保留我的对象数组,以便以后可以遍历它。所以我修改为

                        	var indexer = {};
                        	for (var i = 0; i < array.length; i++) {
                        	    indexer[array[i].id] = parseInt(i);
                        	}
                        	
                        	//Then you can access object properties in your array using 
                        	array[indexer[id]].property

                        【讨论】:

                        • 使用与查找数组中的项目最快的解决方案相同。但是 parseInt 在这里是多余的。
                        【解决方案28】:

                        利用:

                        var retObj ={};
                        $.each(ArrayOfObjects, function (index, obj) {
                        
                                if (obj.id === '5') { // id.toString() if it is int
                        
                                    retObj = obj;
                                    return false;
                                }
                            });
                        return retObj;
                        

                        它应该通过 id 返回一个对象。

                        【讨论】:

                        • 您可以使用 return obj.id === 5 来缩短代码吗?对象:假;我经常使用 $.each 来遍历数组。
                        • @marcel:那行不通。由于返回 false 将结束循环,因此它只会找到数组中第一项的对象。
                        【解决方案29】:

                        此解决方案也可能有帮助:

                        Array.prototype.grep = function (key, value) {
                            var that = this, ret = [];
                            this.forEach(function (elem, index) {
                                if (elem[key] === value) {
                                    ret.push(that[index]);
                                }
                            });
                            return ret.length < 2 ? ret[0] : ret;
                        };
                        var bar = myArray.grep("id","45");
                        

                        我做的就像$.grep,如果找到一个对象,功能将返回对象,而不是数组。

                        【讨论】:

                        • 不要修改不属于您的对象。
                        • @Gothdo 我同意。如果有人不知道function will return the object, rather than an array 可能会弄错,但我认为这取决于用户。
                        【解决方案30】:

                        动态缓存查找

                        在这个解决方案中,当我们搜索某个对象时,我们将它保存在缓存中。这是“始终搜索解决方案”和“在预计算中为每个对象创建哈希映射”之间的中间点。

                        let cachedFind = (()=>{
                          let cache = new Map();
                          return (arr,id,el=null) => 
                            cache.get(id) || (el=arr.find(o=> o.id==id), cache.set(id,el), el);
                        })();
                        
                        
                        // ---------
                        // TEST
                        // ---------
                        
                        let myArray = [...Array(100000)].map((x,i)=> ({'id':`${i}`, 'foo':`bar_${i}`}));
                        
                        // example usage
                        
                        console.log( cachedFind(myArray,'1234').foo );
                        
                        
                        
                        
                        
                        // Benchmark
                        
                        let bench = (id) => {
                          console.time   ('time for '+id ); 
                          console.log    ( cachedFind(myArray,id).foo );  // FIND
                          console.timeEnd('time for '+id );
                        }
                        
                        console.log('----- no cached -----');
                        bench(50000);
                        bench(79980);
                        bench(99990);
                        console.log('-----  cached   -----');
                        bench(79980); // cached
                        bench(99990); // cached

                        【讨论】:

                          猜你喜欢
                          • 2022-01-18
                          相关资源
                          最近更新 更多