【问题标题】:In an array of objects, fastest way to find the index of an object whose attributes match a search在对象数组中,找到属性与搜索匹配的对象索引的最快方法
【发布时间】:2023-01-10 14:35:33
【问题描述】:

我一直在网上冲浪,试图找到一种有效的方法来做到这一点,但一无所获。我有一组看起来像这样的对象:

array[i].id = some number;
array[i].name = some name;

我想做的是找到id等于的对象的INDEXES,例如0,1,2,3或4之一。 我想我可以做类似的事情:

var indexes = [];
for(i=0; i<array.length; i++) {
  (array[i].id === 0) ? { indexes[0] = i }
  (array[i].id === 1) ? { indexes[1] = i }
  (array[i].id === 2) ? { indexes[2] = i }
  (array[i].id === 3) ? { indexes[3] = i }
  (array[i].id === 4) ? { indexes[4] = i }
}

虽然这可行,但它看起来非常昂贵且缓慢(更不用说丑陋了),尤其是在 array.length 可能很大的情况下。关于如何改善这一点的任何想法?我想过以某种方式使用 array.indexOf 但我不知道如何强制语法。这个

array.indexOf(this.id === 0);

例如,返回 undefined,因为它可能应该如此。

【问题讨论】:

  • 如果你有一个普通的旧数组,你所能做的就是迭代。这就是数组,一堆按数组索引排序的对象。
  • 今天刚刚看到这篇文章,对于所有后来者来说,ECMAScript 2015 中有一个新的数组方法Array.prototype.findIndex()。接受的答案非常棒。
  • 我是 ES6 语法的粉丝(如果需要对旧版浏览器的支持,请使用 polyfill)。 ES7+ES8 将是未来
  • 仅供参考,如果您希望能够快速查找,那么您可能不应该使用数组,而应该使用字典(Id,对象)

标签: javascript arrays indexof


【解决方案1】:

也许您想使用高阶函数,例如“map”。 假设您要按“field”属性搜索:

var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor);
var objectFound = array[elementPos];

【讨论】:

  • 这个答案很棒,因为它实际上通过提供索引来回答问题 :)
  • @ZeroAbsolute 您应用的函数(传递给地图)可以返回一个散列字符串,该字符串应该为您的条件给出的每个可能组合提供一个唯一的键。例如:function hashf(el) { return String(el.id) + "_" + String(el.name); }。这只是一个提示:elementPos = array.map(hashf(x)).indexOf(hash({id:3, name:'Pablo'})); 显然,我提供的散列函数并非对所有情况都有效,因为 '_' 可能构成您的值的一部分,但这只是一个简单的示例,您可以找出不同的散列方法。
  • 如果找不到,这会返回什么?我假设 -1,只是好奇。我会做实验。
  • @NathanC.Tresch 它返回 -1,因为它是 indexOf 找不到给定值时的返回值。
  • 大家好,除了使用两种方法map, indexOf,您可以只使用一种名为findIndex...... 例如:[{id:1},{id:2},{id:3},{id:4}].findIndex(function(obj){return obj.id == 3}) OR [{id:1},{id:2},{id:3},{id:4}].findIndex(obj =&gt; obj.id == 3)
【解决方案2】:

在数组中查找元素索引的最简单和最容易的方法。

ES5语法:[{id:1},{id:2},{id:3},{id:4}].findIndex(function(obj){return obj.id == 3})

ES6语法:[{id:1},{id:2},{id:3},{id:4}].findIndex(obj =&gt; obj.id == 3)

【讨论】:

  • 我相信这是最优雅的解决方案。对于那些担心向后兼容性的人,您可以在 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 找到 findIndex 的 polyfill@
  • 我在我的 ES6 lint 工具中收到一条警告,指出此处使用的 obj.id == 3 运算符可能会导致意外的类型转换,因此请改用 obj.id === 3 运算符,它会测试相等的值和类型。
  • 这个答案至少比上面接受的答案快 3.5 倍。使用var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor);花费了 0.03500000002532033 毫秒使用[{id:1},{id:2},{id:3},{id:4}].findIndex(obj =&gt; obj.id == 3)花费了 0.00999999747378752 毫秒。
  • 这个答案是最有效的,因为它不会迭代整个数组。选定的答案将映射完整的数组,然后是 findIndex,它必然会遍历整个数组一次
  • 这是正确的获取方式指数const index = this.pages.findIndex(object =&gt; { return object.id === id; }); console.log('index', index);
【解决方案3】:

新的 Array 方法 .filter() 可以很好地解决这个问题:

var filteredArray = array.filter(function (element) { 
    return element.id === 0;
});

jQuery 也可以用 .grep() 做到这一点

编辑:值得一提的是,这两个函数只是在后台迭代,它们与滚动您自己的过滤器函数之间不会有明显的性能差异,但为什么要重新发明轮子。

【讨论】:

  • +1,我总是忘记对象上这样的内置函数。
  • 这不会返回索引。
  • 这并没有回答这个具体问题,但对我有很大帮助!谢谢!
  • 这不会返回索引。
【解决方案4】:

如果您关心性能,请不要使用寻找或者筛选或者地图或任何上述讨论的方法

这是一个演示最快方法的示例。 HERE为实测链接

设置块

var items = []

for(var i = 0; i < 1000; i++) {
    items.push({id: i + 1})
}

var find = 523

最快的方法

var index = -1
for(var i = 0; i < items.length; i++) {
    if(items[i].id === find) {
        index = i;
        break;
    }
}

较慢的方法

items.findIndex(item => item.id === find)

最慢的方法

items.map(item => item.id).indexOf(find);

【讨论】:

    【解决方案5】:

    由于使用常规数组find没有答案:

    var one = {id: 1, name: 'one'};
    var two = {id: 2, name:'two'}
    var arr = [one, two] 
         
    var found = arr.find((a) => a.id === 2) 
    
    console.log(found === two) // true
    
    console.log(arr.indexOf(found)) // 1

    【讨论】:

      【解决方案6】:
      array.forEach(function (elem, i) {  // iterate over all elements of array
          indexes[elem.id] = i;           // take the found id as index for the
      });                                 // indexes array and assign i
      

      结果是 id 的查找列表。使用给定的 id 我们可以获得记录的索引。

      【讨论】:

        【解决方案7】:

        const index = array.findIndex(item =&gt; item.id === 'your-id');

        这应该为您提供 id === your-id 数组中的项目索引

        array = [ {id:1}, {id:2} ];
        
        const index = array.findIndex(item => item.id === 2);
        
        console.log(index);

        【讨论】:

          【解决方案8】:
          var indices = [];
          var IDs = [0, 1, 2, 3, 4];
          
          for(var i = 0, len = array.length; i < len; i++) {
              for(var j = 0; j < IDs.length; j++) {
                  if(array[i].id == ID) indices.push(i);
              }
          }
          

          【讨论】:

            【解决方案9】:

            一种使用 ES6 的新方法

            let picked_element = array.filter(element => element.id === 0);
            

            【讨论】:

              【解决方案10】:

              使用 ES6 map 函数:

              let idToFind = 3;
              let index = someArray.map(obj => obj.id).indexOf(idToFind);
              

              【讨论】:

                【解决方案11】:

                正如@PirateBay 所指出的,有时旧方法是最好的。

                对于 ES 6/7,“.find”也非常快并且在匹配时停止(不像 .map 或 .filter)

                items.find(e => e.id === find)?.id
                

                【讨论】:

                  【解决方案12】:

                  在我看来,您可以创建一个带有回调的简单迭代器进行测试。像这样:

                  function findElements(array, predicate)
                  {
                      var matchingIndices = [];
                  
                      for(var j = 0; j < array.length; j++)
                      {
                          if(predicate(array[j]))
                             matchingIndices.push(j);
                      }
                  
                      return matchingIndices;
                  }
                  

                  然后你可以这样调用:

                  var someArray = [
                       { id: 1, text: "Hello" },
                       { id: 2, text: "World" },
                       { id: 3, text: "Sup" },
                       { id: 4, text: "Dawg" }
                    ];
                  
                  var matchingIndices = findElements(someArray, function(item)
                     {
                          return item.id % 2 == 0;
                     });
                  
                  // Should have an array of [1, 3] as the indexes that matched
                  

                  【讨论】:

                    【解决方案13】:

                    调整 Tejs 对 mongoDB 和 Robomongo 的回答我改变了

                    matchingIndices.push(j);
                    

                    matchingIndices.push(NumberInt(j+1));
                    

                    【讨论】:

                      【解决方案14】:

                      总结上面所有的好答案和我关于从一些评论中找到所有索引的额外答案。

                      1. 返回第一次出现的索引。

                        const array = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 2 }];
                        const idYourAreLookingFor = 2;
                        
                        //ES5 
                        //Output: 1
                        array.map(function (x) { return x.id; }).indexOf(idYourAreLookingFor);
                        
                        //ES6 
                        //Output: 1
                        array.findIndex(obj => obj.id === idYourAreLookingFor);
                        1. 使用 reduce 返回所有出现的索引数组。

                        const array = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 2 }]
                        const idYourAreLookingFor = 2;
                        
                        //ES5
                        //Output: [1, 4]
                        array.reduce(function (acc, obj, i) {
                          if (obj.id === idYourAreLookingFor)
                            acc.push(i);
                          return acc;
                        }, []);
                        
                        //ES6
                        //Output: [1, 4]
                        array.reduce((acc, obj, i) => (obj.id === idYourAreLookingFor) ? acc.concat(i) : acc, [])

                      【讨论】:

                        【解决方案15】:

                        我创建了一个名为 super-array 的小型实用程序,您可以在其中通过复杂度为 O(1) 的唯一标识符访问数组中的项目。例子:

                        const SuperArray = require('super-array');
                        
                        const myArray = new SuperArray([
                          {id: 'ab1', name: 'John'},
                          {id: 'ab2', name: 'Peter'},
                        ]);
                        
                        console.log(myArray.get('ab1')); // {id: 'ab1', name: 'John'}
                        console.log(myArray.get('ab2')); // {id: 'ab2', name: 'Peter'}
                        

                        【讨论】:

                        • 在到处张贴之前,您可能需要阅读How to offer personal open-source libraries?
                        • @MartijnPieters 我只针对几个相关问题发布了它,并且该项目是麻省理工学院免费的,这有什么关系?也许你可以更宽容一点。
                        【解决方案16】:

                        由于我还不能评论,我想根据 Umair Ahmed 发布的方法展示我使用的解决方案,但是当你想搜索一个键而不是一个值时:

                        [{"a":true}, {"f":true}, {"g":false}]
                        .findIndex(function(element){return Object.keys(element)[0] == "g"});
                        

                        我知道它没有回答扩展的问题,但标题没有具体说明每个对象想要什么,所以我想谦虚地分享这个,以免将来让其他人头疼,而我取消启动它可能不是最快的解决方案。

                        【讨论】:

                          【解决方案17】:
                          var test = [
                            {id:1, test: 1},
                            {id:2, test: 2},
                            {id:2, test: 2}
                          ];
                          
                          var result = test.findIndex(findIndex, '2');
                          
                          console.log(result);
                          
                          function findIndex(object) {
                            return object.id == this;
                          }
                          

                          将返回索引 1(仅适用于 ES 2016)

                          【讨论】:

                            【解决方案18】:

                            我喜欢这种方法,因为它很容易与对象中的任何值进行比较,无论它的嵌套有多深。

                             while(i<myArray.length && myArray[i].data.value!==value){
                              i++; 
                            }
                            // i now hows the index value for the match. 
                             console.log("Index ->",i );
                            

                            【讨论】:

                              【解决方案19】:

                              一种基于特定匹配项在数组中查找对象索引的简单方法。

                              //list of bookings
                              const bookings = [
                                      { status: "accepted", _id: "6055cadd062eb5153c089121", title: "This is test               title", user: "id", team: "id" },
                                      { status: "pending", _id: "6055cb33062eb5153c089122", title: "title1",                   description: "test description", user: "id", team: "id" },
                                      { status: "accepted", _id: "6055cb3d062eb5153c089123", title: "title2",                   description: "test description", user: "id", team: "id" }
                                      ]
                                  
                              //return index of the element if find else return -1 
                              const findIndex = (booking) => bookings.findIndex((b, index) => {
                                      if (b._id === booking._id) return true    
                              })
                                      
                              //test 1
                              let booking = { status: "pending", _id: "6055cb33062eb5153c089122", title: "title2",             description: "test description", user: "id", team: "id" }
                              console.log("index >>> ", findIndex(booking))
                              //output : 1
                                  
                              //test 2
                              booking = { status: "rejected", _id: "6055cb33062eb5153c089198", title: "title3",                 description: "test description", user: "id", team: "id" }
                              console.log("index >>> ", findIndex(booking))
                              //output : -1
                                  
                              //test 3
                              const id = '6055cb3d062eb5153c089123'
                              console.log("index >>> ", findIndex({ _id: id }))
                              //output : 2

                              【讨论】:

                                猜你喜欢
                                • 2012-05-20
                                • 1970-01-01
                                • 1970-01-01
                                • 2021-09-07
                                • 1970-01-01
                                • 2021-01-18
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                相关资源
                                最近更新 更多