如何通过JavaScript数组中的键和值查找对象的索引


74

鉴于:

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

通缉:

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

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



2
是的,用例相同,但是我发现我的问题更通用,例如,如果您没有要搜索的名为“ id”的键,则命中率更高。
return1.at

@FelixKling我不认为这是重复的,因为它试图获取与对象相对的索引(您指出的问题没有解决我的问题,但这个问题确实解决了)。
jcuenod '16

Answers:


153

功能方法

这些天,所有很酷的孩子都在做函数式编程(你好,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功能。
wonsuc

现在,假设您想知道该行中比萨的索引{ "attr1": "bob", "attr2": "pizza" },即“ 1”,您将如何做?或者,给定"pizza"您想知道哪个值对应的值property name(即attr2),假设我们位于第0行,您将如何做?
约翰加拉西

也许它已更新。findIndex现在返回-1或找到的索引位置。
VolkanGüven20年

20

如果要检查对象本身而不干扰原型,请使用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
+1,但为什么不只返回i(而不是$ .inArray(array [i],array);)呢?
Me.Name 2012年

1
为什么用i += 1代替i++
Amberlamps 2012年

1
为什么使用'array [i] .hasOwnProperty(attr)'而不是'array [i] [attr]'?
阿兰·贝克

@ AlainSaint圣埃蒂安看到stackoverflow.com/questions/135448/...
return1.at

1
我建议在“ for”循环后添加“ return -1”,以防万一找不到元素(类似于javascript的“ indexOf”或jquery的“ $ .inArray”)
schellmax 2012年

8

使用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 );
   });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

使用for循环

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


链接已断开😉–
亚历山大

4

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

如果您对实现“人民”的方式不满意,那么获取合适人选的更像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;

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


不会影响我的用例,但可能会对其他人有所帮助。我应该更新我的问题以获取更通用的属性名称,以使其更加清楚。
return1.at 2012年

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()'的一个很好的理由?
阿兰·贝克

我不完全记得为什么
要走

1

这样做:

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

请参考现场演示


1
完全不需要jQuery。
lukas

1

您还可以通过扩展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)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.