【问题标题】:How to find index of an object by key and value in an javascript array如何通过javascript数组中的键和值查找对象的索引
【发布时间】:2012-06-29 07:53:52
【问题描述】:

鉴于:

var peoples = [
  { "attr1": "bob", "attr2": "pizza" },
  { "attr1": "john", "attr2": "sushi" },
  { "attr1": "larry", "attr2": "hummus" }
];

通缉:

attr === value 所在的对象索引,例如 attr1 === "john"attr2 === "hummus"

更新: 请仔细阅读我的问题,我不想通过 $.inArray 找到对象,也不想获取特定对象属性的值。请考虑这个作为你的答案。谢谢!

【问题讨论】:

  • 是的,相同的用例,但我发现我的问题更通用,例如,如果您没有要搜索的名为“id”的键,则命中率会更高。
  • @FelixKling 我不认为这是重复的,因为它试图获取 index 而不是 object (你指出的问题to 没有解决我的问题,但这个解决了)。

标签: javascript jquery


【解决方案1】:

函数式方法

现在所有酷孩子都在做函数式编程(你好 React 用户),所以我想我会给出函数式解决方案。在我看来,它实际上比迄今为止提出的命令式 foreach 循环要好得多,并且使用 ES6 语法它非常优雅。

更新

现在有一种称为findIndex 的好方法,它采用一个函数,该函数根据数组元素是否匹配返回true/false(一如既往,检查浏览器兼容性)。

var index = peoples.findIndex(function(person) {
  return person.attr1 == "john"
});

使用 ES6 语法,你可以这样写:

var index = peoples.findIndex(p => p.attr1 == "john");

(旧)函数式方法

TL;DR

如果您正在寻找 index 其中peoples[index].attr1 == "john" 使用:

var index = peoples.map(function(o) { return o.attr1; }).indexOf("john");

说明

第 1 步

使用.map() 获取给定特定键的值数组:

var values = object_array.map(function(o) { return o.your_key; });

上面的行带你从这里开始:

var peoples = [
  { "attr1": "bob", "attr2": "pizza" },
  { "attr1": "john", "attr2": "sushi" },
  { "attr1": "larry", "attr2": "hummus" }
];

到这里:

var values = [ "bob", "john", "larry" ];

第 2 步

现在我们只需使用.indexOf() 来查找我们想要的键的索引(当然,这也是我们要查找的对象的索引):

var index = values.indexOf(your_value);

解决方案

我们结合了以上所有内容:

var index = peoples.map(function(o) { return o.attr1; }).indexOf("john");

或者,如果你更喜欢 ES6 语法:

var index = peoples.map((o) => o.attr1).indexOf("john");

演示:

var peoples = [
  { "attr1": "bob", "attr2": "pizza" },
  { "attr1": "john", "attr2": "sushi" },
  { "attr1": "larry", "attr2": "hummus" }
];

var index = peoples.map(function(o) { return o.attr1; }).indexOf("john");
console.log("index of 'john': " + index);

var index = peoples.map((o) => o.attr1).indexOf("larry");
console.log("index of 'larry': " + index);

var index = peoples.map(function(o) { return o.attr1; }).indexOf("fred");
console.log("index of 'fred': " + index);

var index = peoples.map((o) => o.attr2).indexOf("pizza");
console.log("index of 'pizza' in 'attr2': " + index);

【讨论】:

  • 很遗憾IE不支持findIndex功能。
  • 现在假设您想知道{ "attr1": "bob", "attr2": "pizza" } 行中的比萨饼索引,即“1”,您会怎么做?或者,给定值"pizza",你想知道对应的property name(即:attr2),假设我们在第0行,你会怎么做?
  • 可能更新了。 findIndex 现在返回 -1 或找到的索引位置。
【解决方案2】:

虽然我认为值得一提,但不是对您问题的直接回答,因为您的问题似乎适合“在键值存储中按名称获取事物”的一般情况。

如果您对“peoples”的实现方式并不严格,那么找到合适人选的更类似于 JavaScript 的方式可能是:

var peoples = {
  "bob":  { "dinner": "pizza" },
  "john": { "dinner": "sushi" },
  "larry" { "dinner": "hummus" }
};

// If people is implemented this way, then
// you can get values from their name, like :
var theGuy = peoples["john"];

// You can event get directly to the values
var thatGuysPrefferedDinner = peoples["john"].dinner;

希望如果这不是您想要的答案,它可能会对对“键/值”问题感兴趣的人有所帮助。

【讨论】:

  • 这不会影响我的用例,但可能对其他人有帮助。我应该更新我的问题以获得更通用的属性名称以使其清楚。
【解决方案3】:
function getIndexByAttribute(list, attr, val){
    var result = null;
    $.each(list, function(index, item){
        if(item[attr].toString() == val.toString()){
           result = index;
           return false;     // breaks the $.each() loop
        }
    });
    return result;
}

【讨论】:

  • 只是为了澄清一件事:'return false' 似乎没有必要。可以不用,但这是一个很好的优化,因为它打破了“$.each()”循环。做得好!另一方面,调用 '.toString()' 很奇怪(为什么不比较值?),如果在 'item' 上未定义 'attr' 或 val 为 'null',则可能会导致错误。 . 还是我错过了在这里使用 'toString()' 的一个很好的理由?
  • 我不完全记得我为什么要那样做,但似乎记得这是因为当值是数字时发生了一些冲突
【解决方案4】:

如果您想在不干扰原型的情况下检查对象本身,请使用hasOwnProperty()

var getIndexIfObjWithOwnAttr = function(array, attr, value) {
    for(var i = 0; i < array.length; i++) {
        if(array[i].hasOwnProperty(attr) && array[i][attr] === value) {
            return i;
        }
    }
    return -1;
}

还包括原型属性,使用:

var getIndexIfObjWithAttr = function(array, attr, value) {
    for(var i = 0; i < array.length; i++) {
        if(array[i][attr] === value) {
            return i;
        }
    }
    return -1;
}

【讨论】:

  • +1 ,但为什么不只返回 i (而不是 $.inArray(array[i], array); )?
  • 你为什么用i += 1而不是i++
  • 为什么使用'array[i].hasOwnProperty(attr)'而不是'array[i][attr]'?
  • 我建议在'for'循环之后添加'return -1',以防找不到元素(类似于javascript的'indexOf'或jquery的'$.inArray')
【解决方案5】:

使用 jQuery .each()

var peoples = [
  { "attr1": "bob", "attr2": "pizza" },
  { "attr1": "john", "attr2": "sushi" },
  { "attr1": "larry", "attr2": "hummus" }
];

$.each(peoples, function(index, obj) {
   $.each(obj, function(attr, value) {
      console.log( attr + ' == ' + value );
   });
});
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;

使用 for-loop

var peoples = [
  { "attr1": "bob", "attr2": "pizza" },
  { "attr1": "john", "attr2": "sushi" },
  { "attr1": "larry", "attr2": "hummus" }
];

for (var i = 0; i < peoples.length; i++) {
  for (var key in peoples[i]) {
    console.log(key + ' == ' + peoples[i][key]);
  }
}

【讨论】:

  • 链接坏了?
【解决方案6】:

您还可以通过扩展 JavaScript 使其成为可重用的方法:

Array.prototype.findIndexBy = function(key, value) {
    return this.findIndex(item => item[key] === value)
}

const peoples = [{name: 'john'}]
const cats = [{id: 1, name: 'kitty'}]

peoples.findIndexBy('name', 'john')
cats.findIndexBy('id', 1)

【讨论】:

    【解决方案7】:

    这样做:-

    var peoples = [
      { "name": "bob", "dinner": "pizza" },
      { "name": "john", "dinner": "sushi" },
      { "name": "larry", "dinner": "hummus" }
    ];
    
    $.each(peoples, function(i, val) {
        $.each(val, function(key, name) {
            if (name === "john")
                alert(key + " : " + name);
        });
    });
    

    输出:

    name : john
    

    参考LIVE DEMO

    【讨论】:

    • 绝对不需要 jQuery。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-17
    • 2017-01-28
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    相关资源
    最近更新 更多