Как получить индекс объекта по его свойству в javascript
Например у меня есть:
var Data = [
{id_list:1, name:'Nick',token:'312312'},{id_list:2,name:'John',token:'123123'}
]
Затем я хочу отсортировать / перевернуть этот объект по имени, например. Я получаю что-то вроде этого:
var Data = [
{id_list:2,name:'John',token:'123123'},{id_list:1, name:'Nick',token:'312312'}
]
И теперь я хочу знать индекс объекта со свойством name='John', чтобы получить значение токена свойства.
22 ответа
Как показывают другие ответы, циклически проходить по массиву, вероятно, является наилучшим способом. Но я бы поместил его в свою собственную функцию и сделал его немного более абстрактным:
function findWithAttr(array, attr, value) {
for(var i = 0; i < array.length; i += 1) {
if(array[i][attr] === value) {
return i;
}
}
return -1;
}
var Data = [
{id_list: 2, name: 'John', token: '123123'},
{id_list: 1, name: 'Nick', token: '312312'}
];
При этом вы можете не только найти, какой из них содержит "Джон", но и найти, который содержит токен "312312":
findWithAttr(Data, 'name', 'John'); // returns 0
findWithAttr(Data, 'token', '312312'); // returns 1
findWithAttr(Data, 'id_list', '10'); // returns -1
РЕДАКТИРОВАТЬ: Обновлена функция, чтобы возвращать -1, когда не найден, поэтому она следует той же конструкции, что и Array.prototype.indexOf()
Так как сортировка уже дана ответ. Я просто собираюсь предложить другой элегантный способ получить indexOf свойства в вашем массиве
Ваш пример:
var Data = [
{id_list:1, name:'Nick',token:'312312'},
{id_list:2,name:'John',token:'123123'}
]
Ты можешь сделать:
var index = Data.map(function(e) { return e.name; }).indexOf('Nick');
Array.prototype.map
недоступно в IE7 или IE8. ES5 Совместимость
И вот он с ES6 и синтаксисом стрелки, который еще проще:
const index = Data.map(e => e.name).indexOf('Nick');
Если вы в порядке с ES6. Массивы теперь имеют функцию findIndex. Что означает, что вы можете сделать что-то вроде этого:
const index = Data.findIndex(item => item.name === 'John');
Если у вас есть проблемы с IE, вы можете использовать функцию map(), которая поддерживается начиная с 9.0:
var index = Data.map(item => item.name).indexOf("Nick");
var index = Data.findIndex(item => item.name == "John")
Который является упрощенной версией:
var index = Data.findIndex(function(item){ return item.name == "John"})
С mozilla.org:
Метод findIndex() возвращает индекс первого элемента в массиве, который удовлетворяет предоставленной функции тестирования. В противном случае -1 возвращается.
Единственный известный мне способ - перебрать весь массив:
var index=-1;
for(var i=0;i<Data.length;i++)
if(Data[i].name==="John"){index=i;break;}
или без учета регистра:
var index=-1;
for(var i=0;i<Data.length;i++)
if(Data[i].name.toLowerCase()==="john"){index=i;break;}
Индекс переменной результата содержит индекс объекта или -1, если не найден.
вы можете использовать метод фильтра
const filteredData = data.filter(e => e.name !== 'john');
Прототипный способ
(function(){
if (!Array.prototype.indexOfPropertyValue){
Array.prototype.indexOfPropertyValue = function(prop,value){
for (var index = 0; index < this.length; index++){
if (this[index][prop]){
if (this[index][prop] == value){
return index;
}
}
}
return -1;
}
}
})();
// usage:
var Data = [
{id_list:1, name:'Nick',token:'312312'},{id_list:2,name:'John',token:'123123'}];
Data.indexOfPropertyValue('name','John'); // returns 1 (index of array);
Data.indexOfPropertyValue('name','Invalid name') // returns -1 (no result);
var indexOfArray = Data.indexOfPropertyValue('name','John');
Data[indexOfArray] // returns desired object.
Почему бы вам не использовать небольшой обходной путь?
Создайте новый массив с именами в качестве индексов. после этого все поиски будут использовать индексы. Итак, только одна петля. После этого вам не нужно перебирать все элементы!
var Data = [
{id_list:1, name:'Nick',token:'312312'},{id_list:2,name:'John',token:'123123'}
]
var searchArr = []
Data.forEach(function(one){
searchArr[one.name]=one;
})
console.log(searchArr['Nick'])
http://jsbin.com/xibala/1/edit
живой пример.
Вы можете использовать findIndex в библиотеке Lodash .
Пример:
var users = [
{ 'user': 'barney', 'active': false },
{ 'user': 'fred', 'active': false },
{ 'user': 'pebbles', 'active': true }
];
_.findIndex(users, function(o) { return o.user == 'barney'; });
// => 0
// The `_.matches` iteratee shorthand.
_.findIndex(users, { 'user': 'fred', 'active': false });
// => 1
// The `_.matchesProperty` iteratee shorthand.
_.findIndex(users, ['active', false]);
// => 0
// The `_.property` iteratee shorthand.
_.findIndex(users, 'active');
// => 2
var fields = {
teste:
{
Acess:
{
Edit: true,
View: false
}
},
teste1:
{
Acess:
{
Edit: false,
View: false
}
}
};
console.log(find(fields,'teste'));
function find(fields,field){
for(key in fields){
if(key == field){
return true;
}
}
return false;
}
Если у вас есть один объект с несколькими объектами внутри, если вы хотите знать, включен ли какой-либо объект в главный объект, просто поместите find(MasterObject,'Object to Search'), эта функция вернет ответ, если он существует или нет (TRUE или FALSE), Я надеюсь помочь с этим, можете увидеть пример на JSFiddle.
let indexOf = -1;
let theProperty = "value"
let searchFor = "something";
theArray.every(function (element, index) {
if (element[theProperty] === searchFor) {
indexOf = index;
return false;
}
return true;
});
Как насчет этого?:
Data.indexOf(_.find(Data, function(element) {
return element.name === 'John';
}));
Предполагая, что вы используете lodash или underscorejs.
Если вы хотите получить значение токена свойства, вы также можете попробовать это
let data=[
{ id_list: 1, name: 'Nick', token: '312312' },
{ id_list: 2, name: 'John', token: '123123' },
]
let resultingToken = data[_.findKey(data,['name','John'])].token
где _.findKey - функция lodash
Просто пройдите через ваш массив и найдите позицию:
var i = 0;
for(var item in Data) {
if(Data[item].name == 'John')
break;
i++;
}
alert(i);
Расширенный ответ Криса Пикетта, потому что в моем случае мне нужно было искать глубже, чем один уровень атрибута:
function findWithAttr(array, attr, value) {
if (attr.indexOf('.') >= 0) {
var split = attr.split('.');
var attr1 = split[0];
var attr2 = split[1];
for(var i = 0; i < array.length; i += 1) {
if(array[i][attr1][attr2] === value) {
return i;
}
}
} else {
for(var i = 0; i < array.length; i += 1) {
if(array[i][attr] === value) {
return i;
}
}
};
};
Вы можете передать attr1.attr2 в функцию
Это может быть полезно
function showProps(obj, objName) {
var result = "";
for (var i in obj)
result += objName + "." + i + " = " + obj[i] + "\n";
return result;
}
Скопировал это из https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects
Вы можете использовать Array.sort, используя пользовательскую функцию в качестве параметра для определения вашего механизма сортировки.
В вашем примере это даст:
var Data = [
{id_list:1, name:'Nick',token:'312312'},{id_list:2,name:'John',token:'123123'}
]
Data.sort(function(a, b){
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
});
alert("First name is : " + Data[0].name); // alerts 'John'
alert("Second name is : " + Data[1].name); // alerts 'Nick'
Функция сортировки должна возвращать -1, если a должно предшествовать b, 1, если a следует после b, и 0, если оба равны. Вам нужно определить правильную логику в вашей функции сортировки для сортировки массива.
Изменить: пропустил последнюю часть вашего вопроса, где вы хотите знать индекс. Вы должны были бы пройтись по массиву, чтобы найти это, как сказали другие.
Возможно, вам помогут методы Object.keys, Object.entries и Object.values.
В качестве альтернативы ответу Аттанасио Руиса из Германии вы можете исключить второй цикл, используя Array.reduce() вместо Array.map();
var Data = [
{ name: 'hypno7oad' }
]
var indexOfTarget = Data.reduce(function (indexOfTarget, element, currentIndex) {
return (element.name === 'hypno7oad') ? currentIndex : indexOfTarget;
}, -1);
Using underscore:
var index = _.indexOf(_.pluck(item , 'name'), 'Nick');