2013-04-14 2 views
120

У меня есть массив как это:Получить индекс объекта внутри массива, соответствующие условию

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

Как я могу получить индекс объекта, который соответствует условию, без перебора всего массива ?

Например, с учетом prop2=="yutu", я хочу получить индекс 1.

Я видел .indexOf(), но думаю, что он используется для простых массивов, таких как ["a1","a2",...]. Я также проверил $.grep(), но это возвращает объекты, а не индекс.

ответ

267

По состоянию на 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);

Он поддерживается в GC, FF и Edge, для MSIEs есть polyfill на связанной странице.

Старый ответ:

С JQuery:

indexes = $.map(list, function(obj, index) { 
    if(obj.prop2 == "yutu") { 
     return index; 
    } 
}) 

firstIndex = indexes[0] 

Без JQuery, немного сложнее:

indexes = list.map(function(obj, index) { 
    if(obj.prop2 == "yutu") { 
     return index; 
    } 
}).filter(isFinite) 
+2

Я не вижу необходимости в временном массиве здесь. Просто используйте тот факт, что функция итератора закрывается по контексту и использует переменную. Кроме того, версия не-jQuery не работает (предположим, что она найдена в индексе '0'?). * Оба решения имеют больше итераций, чем требуется, что является менее идеальным, если массив большой (хотя вероятность того, что он будет настолько большой, что человек заметит, низкий, если только поисковые запросы не происходят ** много **). –

+2

@ T.J.Crowder: не-jQuery версия исправлена, спасибо. – georg

+0

@ thg435: По-прежнему думаю, что это немного машина Рубе Голдберга, где простой рычаг мог бы сделать трюк. :-) Но эй, это работает! –

18

Как я могу получить индекс объекта, который соответствует условию (без итерации по массиву)?

Вы не можете, что-то должен перебирать массив (по крайней мере, один раз).

Если состояние сильно изменилось, вам придется пройтись и посмотреть на объекты в нем, чтобы увидеть, соответствуют ли они условию. Однако, в системе с функциями ES5 (или если вы установите подкладку), что итерация может быть сделана достаточно лаконично:

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

Это использует новый (МОГ) Array#some function, который перебирает записи в массиве, пока функция, которую вы ему даете, возвращает true. Функция, которую я ему предоставил, сохраняет индекс соответствующей записи, а затем возвращает true, чтобы остановить итерацию.

Или, конечно, просто используйте петлю for. Различные варианты итераций описаны в this other answer.

Но если вы всегда будете использовать такое же свойство для этого поиска, и если значение свойств являются уникальным, вы можете цикл только один раз и создать объект для отображения их:

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

(. или, опять же, вы можете использовать for петлю или любой из your other options)

Тогда, если вам нужно найти запись с prop2 = "yutu", вы можете сделать это:

var entry = prop2map["yutu"]; 

Я называю это «кросс-индексирование» массива. Естественно, если вы удаляете или добавляете записи (или изменяете их значения prop2), вам также необходимо обновить свой объект сопоставления.

+0

Спасибо за объяснение! Решение с jQuery, на которое указывает 'thg435', сделал то, что я хотел ... – amp

1

Почему вы не хотите точно итерации? Новые Array.prototype.forEach отлично подходят для этой цели!

Вы можете использовать двоичное дерево поиска для поиска по одному вызову метода, если хотите. Это аккуратная реализация дерева поиска BTree и Red black в JS - https://github.com/vadimg/js_bintrees - но я не уверен, можете ли вы найти индекс в одно и то же время.

13

Что TJ Crowder сказал, Everyway будет иметь какой-то скрытой итерации, с lodash это будет:

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

, в то время как вы можете просто прокручивать различные способы получения индекса, найти Index - лучшее решение, даже принятое в ES6, в методы собственного массива –

3

Вы можете использовать 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 
5
var index; 
yourArray.some(function (elem, i) { 
    return elem.prop2 === 'yutu' ? (index = i, true) : false; 
}); 

итерацию по всем элементам массива. Он возвращает либо индекс, либо true или false, если условие не совпадает.

Важным является явное возвращаемое значение true (или значение, которое имеет логический результат). Единственного назначения недостаточно, из-за возможного индекса с 0 (Boolean (0) === false), что не приведет к ошибке, но отключит перерыв итерации.

Редактировать

Еще короче версия выше:

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

Что делает ~ персонаж во втором фрагменте? – serkan

+0

@serkan, это [поразрядный NOT '|'] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_NOT) оператор, это короткая версия получения из индекса (с -1) a [правдой] (https://developer.mozilla.org/en-US/docs/Glossary/Truthy)/[falsy] (https://developer.mozilla.org/ en-US/docs/Glossary/Falsy), если существует индекс. –

+0

спасибо Нине, без символа, код работает так, как есть, не так ли? – serkan

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

код Оптимизировать:

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

Почему все они возвращаются истинные и ложные.

0

Георг уже упомянул ES6 имеет Array.findIndex для этого. И некоторые другие ответы обходные пути для ES5 с использованием метода Array.some. более

Один элегантный подход может быть

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

В то же время я хотел бы подчеркнуть, Array.некоторые могут быть реализованы с использованием двоичной или другой эффективной методики поиска. Таким образом, он может работать лучше для цикла в каком-то браузере.

3
var CarId = 23; //Or other property name 

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

Я видел много решений в вышеуказанном виде.

Здесь я использую функцию карты, чтобы найти индекс текста поиска в объекте массива.

Я собираюсь объяснить свой ответ с использованием данных студентов.

  • шаг 1: создать массив объектов для студентов (по желанию вы можете создать свой собственный объект массива).
    var students = [{name:"Rambabu",htno:"1245"},{name:"Divya",htno:"1246"},{name:"poojitha",htno:"1247"},{name:"magitha",htno:"1248"}];

  • шаг 2: Создать переменный текст для поиска
    var studentNameToSearch = "Divya";

  • шаг 3: Создать переменный для хранения согласованного индекса (здесь мы используем функцию карты для итерации).
    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)

Смежные вопросы