【问题标题】:Find object by id in an array of JavaScript objects在 JavaScript 对象数组中按 id 查找对象
【发布时间】:2022-01-18 12:10:39
【问题描述】:

我有一个数组:

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


    如果您想找到它的 index,请使用 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);
    

    旁注:旧版浏览器(如 IE)不支持 find()filter()arrow functions 等方法,因此如果您想支持这些浏览器,您应该使用 Babel 转译您的代码( polyfill)。

    【讨论】:

    • 对于多个测试条件,它会因此类似于:myArray.find(x => x.id === '45' && x.color == 'red').foo
    • 对我来说,迄今为止最好的答案。不需要 jQuery,也不需要创建新的辅助数组。
    • 过滤器其实已经支持回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 中不存在。
    • @de。这里的许多答案在查找唯一值时提供了预期的行为;您基本上可以通过它们提前返回或中断循环(或指示较低级别的构造停止迭代)这一事实来识别它们。有关典型示例,请参阅 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】:

    ECMAScript 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() 返回 undefined,那么您的优化会引发错误。所以这个解决方案只能在保证匹配的情况下使用。
    • @HerbertPeters 如果您想确保始终可以进行空值检查,optional chaining 将非常容易:myArray.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) 的解决方案快得多
      • 令人惊讶的是,Safari 上基于对象 {} (L) 的小型阵列解决方案比传统的 for (E) 慢
      • 令人惊讶的是,Firefox 上基于 Map (K) 的小型阵列解决方案比传统的 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】:

        如果你多次这样做,你可以设置一个 Map (ES6):

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

        然后您可以简单地进行 O(1) 查找:

        map.get(27).foo
        

        【讨论】:

          【解决方案12】:

          正如其他人指出的那样,.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

          【讨论】:

            【解决方案13】:

            使用原生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

            【讨论】:

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

            您可以使用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 的常见概念具有误导性,因为结果与原始集合的长度不同。
            【解决方案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】:

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

                如果你只想要codez:

                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];
                }
                

                【讨论】:

                  【解决方案19】:

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

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

                  array.find( {id: 75} );
                  

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

                  注意 Sugarjs 扩展了原生对象,有些人认为这很邪恶......

                  【讨论】:

                  • 好吧,它邪恶的,因为新的 EcmaScript 版本可能会引入同名的新方法。你猜怎么着,这是exactly what happened with find。我的建议是,如果您想扩展原生原型,请始终使用更具体的名称,将最简单的名称留给未来的标准开发。
                  • 这条评论已经有将近 2 年的历史了,今天我还是宁愿使用 lodash。但是,如果您愿意,可以在 sugarjs 网站上阅读有关此主题的信息。他们对您的意见持良好态度:sugarjs.com/native
                  • 该操作确实特别要求提供 javascript 或 jquery 解决方案
                  【解决方案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,下划线 https://underscorejs.org/#filter

                      【讨论】:

                        【解决方案24】:

                        基于公认的答案:

                        jQuery:

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

                        或 CoffeeScript:

                        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;
                              });
                          }
                          

                          【讨论】:

                          • 如何在嵌套对象中搜索? like pets= false 应该返回两个对象。
                          • 在嵌套循环中对obj.info 使用.filter 方法。 var getPerson = function(name){ return jsonObj.filter(function(obj) { return obj.info.filter(function(info) { return pets === false; }); }); }
                          • 你也可以使用 es6 风格... 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 一样,如果找到一个对象,function 将返回该对象,而不是一个数组。

                          【讨论】:

                          • 不要修改不属于你的对象。
                          • @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

                          【讨论】:

                            猜你喜欢
                            相关资源
                            最近更新 更多