获取匹配条件的数组内对象的索引


320

我有一个像这样的数组:

[{prop1:"abc",prop2:"qwe"},{prop1:"bnmb",prop2:"yutu"},{prop1:"zxvz",prop2:"qwrq"},...]

如何在不迭代整个数组的情况下获取与条件匹配的对象的索引?

例如,给定prop2=="yutu",我想获取index 1

我看到了,.indexOf()但认为它用于类似的简单数组["a1","a2",...]。我也检查了一下,$.grep()但这返回了对象,而不是索引。

Answers:


730

从2016年开始,您应该为此使用Array.findIndex(ES2015 / ES6标准):

a = [
  {prop1:"abc",prop2:"qwe"},
  {prop1:"bnmb",prop2:"yutu"},
  {prop1:"zxvz",prop2:"qwrq"}];
    
index = a.findIndex(x => x.prop2 ==="yutu");

console.log(index);

Google Chrome,Firefox和Edge支持该功能。对于Internet Explorer,在链接页面上有一个polyfill。

业绩说明

函数调用是昂贵的,因此对于非常大的数组,简单的循环将比findIndex

let test = [];

for (let i = 0; i < 1e6; i++)
    test.push({prop: i});


let search = test.length - 1;
let count = 100;

console.time('findIndex/predefined function');
    let fn = obj => obj.prop === search;

    for (let i = 0; i < count; i++)
        test.findIndex(fn);
console.timeEnd('findIndex/predefined function');


console.time('findIndex/dynamic function');
    for (let i = 0; i < count; i++)
        test.findIndex(obj => obj.prop === search);
console.timeEnd('findIndex/dynamic function');


console.time('loop');
    for (let i = 0; i < count; i++) {
        for (let index = 0; index < test.length; index++) {
            if (test[index].prop === search) {
                break;
            }
        }
    }
console.timeEnd('loop');

与大多数优化一样,应谨慎且仅在实际需要时才应用此优化。


3
我没有看到这里需要一个临时数组。只需使用事实,即迭代器函数会关闭上下文并使用变量。另外,非jQuery版本不起作用(假设在索引0?上找到)。两种解决方案的迭代次数都超过了所需的迭代次数,如果数组很大(虽然人们可能会注意到这样大的几率很低,除非查找发生得很多),则迭代效果不理想。
TJ Crowder

@ thg435:仍然认为这是一台Rube Goldberg机器,可以通过简单的操作来完成。:-)但是,它有效!
TJ Crowder

4
您能解释一下x => x.prop2=="yutu"findIndex()的工作原理吗?
阿贝(Abhay Pai)

5
@AbhayPai:与function(x) { return x.prop2=="yutu" }
georg

6
我喜欢使用polyfill的建议。但是,即使使用polyfill,由于使用箭头/ lambda函数,编写的代码在IE11中仍然失败。index = a.findIndex(function (x) { return x.prop2 == "yutu" })改正为已解决的问题,以便使用polyfill代码,findIndex在IE11中起作用
Rick Glos

26

我如何获取对象的索引与条件匹配(不沿数组迭代)?

您不能,某些东西必须遍历数组(至少一次)。

如果条件变化很大,那么您将不得不遍历并查看其中的对象,以查看它们是否符合条件。但是,在具有ES5功能(或如果您安装垫片)的系统上,可以相当简洁地完成该迭代:

var index;
yourArray.some(function(entry, i) {
    if (entry.prop2 == "yutu") {
        index = i;
        return true;
    }
});

Array#some函数使用new(ish)函数,该函数会循环访问数组中的条目,直到为您提供的函数返回true。我给它的函数保存了匹配条目的索引,然后返回true以停止迭代。

或者,当然,只需使用for循环即可。您的各种迭代选项将在此其他答案中介绍

但是,如果您总是要使用相同的属性进行查找,并且属性值是唯一的,则可以循环一次并创建一个对象来映射它们:

var prop2map = {};
yourArray.forEach(function(entry) {
    prop2map[entry.prop2] = entry;
});

(或者再次,您可以使用for循环或任何其他选项。)

然后,如果您需要使用查找条目prop2 = "yutu",则可以执行以下操作:

var entry = prop2map["yutu"];

我称此为“交叉索引”数组。自然,如果删除或添加条目(或更改其prop2值),则也需要更新映射对象。


感谢您的解释!jQuery所指向的解决方案thg435做了我想要的...
amp

21

TJ Crowder所说的,总是会有某种隐藏的迭代,用lodash变成:

var index = _.findIndex(array, {prop2: 'yutu'})

1
尽管您可以通过各种方法循环获取索引,但找到Index是最佳解决方案,甚至在ES6中被本机数组方法采用
Kelly Milligan 2015年

13
var CarId = 23;

//x.VehicleId property to match in the object array
var carIndex = CarsList.map(function (x) { return x.VehicleId; }).indexOf(CarId);

对于基本数组编号,您还可以执行以下操作:

var numberList = [100,200,300,400,500];
var index = numberList.indexOf(200); // 1

如果无法在数组中找到值,则将得到-1。


11
var index;
yourArray.some(function (elem, i) {
    return elem.prop2 === 'yutu' ? (index = i, true) : false;
});

遍历数组的所有元素。如果条件不匹配,则返回索引,则返回true或false。

重要的是显式返回值true(或布尔结果为true的值)。由于可能的索引为0(Boolean(0)=== false),单次分配是不够的,这不会导致错误,但会禁用迭代中断。

编辑

甚至更短的版本:

yourArray.some(function (elem, i) {
    return elem.prop2 === 'yutu' && ~(index = i);
});

〜角色在第二个片段中起什么作用?
serkan '18

@serkan,它是按位NOT|运算符,它是从索引(带有-1)获得真实 / 虚假结果(如果存在索引)的简短版本。
Nina Scholz

感谢Nina,如果没有〜字符,代码将按原样运行,不是吗?
serkan '18

@serkan,您的问题尚不清楚,但如果没有,~它将无法正常工作。
Nina Scholz

1
哦,!!(index = 0)!!~(index = 0)差异确实如此。谢谢!
serkan '18

4

您可以通过以下方式使用Array.prototype.some()(如其他答案中所述):

https://jsfiddle.net/h1d69exj/2/

function findIndexInData(data, property, value) {
    var result = -1;
    data.some(function (item, i) {
        if (item[property] === value) {
            result = i;
            return true;
        }
    });
    return result;
}
var data = [{prop1:"abc",prop2:"qwe"},{prop1:"bnmb",prop2:"yutu"},{prop1:"zxvz",prop2:"qwrq"}]



alert(findIndexInData(data, 'prop2', "yutu")); // shows index of 1

4

我在上面看到了许多解决方案。

在这里,我正在使用map函数在数组对象中查找搜索文本的索引。

我将使用学生数据来解释我的答案。

  • 步骤1:为学生创建数组对象(可选,您可以创建自己的数组对象)。
    var students = [{name:"Rambabu",htno:"1245"},{name:"Divya",htno:"1246"},{name:"poojitha",htno:"1247"},{name:"magitha",htno:"1248"}];

  • 第2步:创建变量以搜索文本
    var studentNameToSearch = "Divya";

  • 步骤3:创建变量以存储匹配的索引(这里我们使用map函数进行迭代)。
    var matchedIndex = students.map(function (obj) { return obj.name; }).indexOf(studentNameToSearch);

var students = [{name:"Rambabu",htno:"1245"},{name:"Divya",htno:"1246"},{name:"poojitha",htno:"1247"},{name:"magitha",htno:"1248"}];

var studentNameToSearch = "Divya";

var matchedIndex = students.map(function (obj) { return obj.name; }).indexOf(studentNameToSearch);

console.log(matchedIndex);

alert("Your search name index in array is:"+matchedIndex)


3
function findIndexByKeyValue(_array, key, value) {
    for (var i = 0; i < _array.length; i++) { 
        if (_array[i][key] == value) {
            return i;
        }
    }
    return -1;
}
var a = [
    {prop1:"abc",prop2:"qwe"},
    {prop1:"bnmb",prop2:"yutu"},
    {prop1:"zxvz",prop2:"qwrq"}];
var index = findIndexByKeyValue(a, 'prop2', 'yutu');
console.log(index);


1

使用Array.reduce()的第一步-没有jQuery

var items = [{id: 331}, {id: 220}, {id: 872}];

var searchIndexForId = 220;
var index = items.reduce(function(searchIndex, item, index){
  if(item.id === searchIndexForId) { 
    console.log('found!');
    searchIndex = index;
  }
  return searchIndex;
}, null);

null如果找不到索引,将返回。


0
var list =  [
                {prop1:"abc",prop2:"qwe"},
                {prop1:"bnmb",prop2:"yutu"},
                {prop1:"zxvz",prop2:"qwrq"}
            ];

var findProp = p => {
    var index = -1;
    $.each(list, (i, o) => {
        if(o.prop2 == p) {
            index = i;
            return false; // break
        }
    });
    return index; // -1 == not found, else == index
}

0

Georg已经提到ES6为此具有Array.findIndex。还有其他一些答案是使用Array.some方法的ES5解决方法。

一种更优雅的方法可以是

var index;
for(index = yourArray.length; index-- > 0 && yourArray[index].prop2 !== "yutu";);

同时,我想强调,Array.some可以用二进制或其他有效的搜索技术来实现。因此,在某些浏览器中,for循环可能会更好。


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.