Jquery как найти объект по атрибуту в массиве
учитывая, что у меня есть массив объектов "цель":
//array of purpose objects:
var purposeObjects = [
{purpose: "daily"},
{purpose: "weekly"},
{purpose: "monthly"}
];
(для простоты я опускаю другие атрибуты)
теперь я хочу иметь метод, который возвращает определенный один из объектов, если найдено соответствующее имя цели.
это не работает:
function findPurpose(purposeName){
return $.grep(purposeObjects, function(){
return this.purpose == purposeName;
});
};
findPurpose("daily");
но на самом деле он возвращает пустой массив:
[]
Я использую JQuery 1.5.2. Я также пробовал с $.каждый (), но не повезло.
По-видимому, большинство методов JQuery предназначены для использования с элементами DOM (например,filter()
.
есть идеи, как этого добиться?
10 ответов:
самый быстрый способ (и он работает даже без jQuery):
var findPurpose = function(purposeName) { for (var i = 0, len = purposeObjects.length; i < len; i++) { if (purposeObjects[i].purpose === purposeName) return purposeObjects[i]; // Return as soon as the object is found } return null; // The object was not found }
Примечание
jQuery $.грэп (или другая функция фильтрации) не является оптимальным решением.
The
$.grep
функция будет петля через все элементы массива, даже если искомый объект уже нашли в петле. Из документации jQuery grep:долларов.метод grep () удаляет элементы из массива по мере необходимости, чтобы все остальные предметы проходят предусмотренный тест. Тест-это функция, которая передается элемент массива и индекс элемента в массиве. Только если тест возвращает true, элемент в массив результата.
вы должны передать ссылку на элемент в функцию, например:
function findPurpose(purposeName){ return $.grep(purposeObjects, function(item){ return item.purpose == purposeName; }); };
Я лично использую более общую функцию, которая работает для любого свойства любого массива:
function lookup(array, prop, value) { for (var i = 0, len = array.length; i < len; i++) if (array[i] && array[i][prop] === value) return array[i]; }
вы просто называете это так:
lookup(purposeObjects, "purpose", "daily");
ошибка в том, что вы не можете использовать
this
в grep, но вы должны использовать ссылку на элемент. Это работает:function findPurpose(purposeName){ return $.grep(purposeObjects, function(n, i){ return n.purpose == purposeName; }); }; findPurpose("daily");
возвращает:
[Object { purpose="daily"}]
использовать подчеркивание.функция js findWhere (http://underscorejs.org/#findWhere):
var purposeObjects = [ {purpose: "daily"}, {purpose: "weekly"}, {purpose: "monthly"} ]; var daily = _.findWhere(purposeObjects, {purpose: 'daily'});
daily
будет равен:{"purpose":"daily"}
вот скрипка:http://jsfiddle.net/spencerw/oqbgc21x/
чтобы вернуть более одного (если у вас больше в вашем массиве) вы могли бы использовать
_.where(...)
лучший, самый быстрый способ
function arrayLookup(array, prop, val) { for (var i = 0, len = array.length; i < len; i++) { if (array[i].hasOwnProperty(prop) && array[i][prop] === val) { return array[i]; } } return null; }
Если Ваш массив на самом деле представляет собой набор объектов JQuery, как насчет простого использования .filter () способ ?
purposeObjects.filter('[purpose="daily"]')
еще одно решение:
function firstOrNull(array, expr) { for (var i = 0; i < array.length; i++) { if (expr(array[i])) return array[i]; } return null; }
использование:
firstOrNull([{ a: 1, b: 2 }, { a: 3, b: 3 }], function(item) { return item.a === 3; });
эта функция не выполняется для каждого элемента из массива (это ценно для больших массивов)
Я создал сервис util для моего углового приложения. Он имеет две функции, которые используют очень часто.
у вас есть объект.сначала получение значения из объекта рекурсивно без выбрасывания неопределенной ошибки.
{prop: { nestedProp1: {nestedProp2: somevalue}}}; получить nestedProp2 2 без неопределенных проверок.
второй массив фильтров на основе
[{prop: { nestedProp1: {nestedProp2: somevalue1}}}, {prop: { nestedProp1: {nestedProp2: somevalue2}}}];
найти объект из массива с nestedProp2=somevalue2
app.service('UtilService', function(httpService) { this.mapStringKeyVal = function(map, field) { var lastIdentifiedVal = null; var parentVal = map; field.split('.').forEach(function(val){ if(parentVal[val]){ lastIdentifiedVal = parentVal[val]; parentVal = parentVal[val]; } }); return lastIdentifiedVal; } this.arrayPropFilter = function(array, field,value) { var lastIdentifiedVal = null; var mapStringKeyVal = this.mapStringKeyVal; array.forEach(function(arrayItem){ var valueFound = mapStringKeyVal(arrayItem,field); if(!lastIdentifiedVal && valueFound && valueFound==value){ lastIdentifiedVal = arrayItem; } }); return lastIdentifiedVal; }});
для решения текущего вопроса. введите UtilService и позвоните,
UtilService.arrayPropFilter(purposeArray,'purpose','daily');
или более продвинутым
UtilService.arrayPropFilter(purposeArray,'purpose.nestedProp1.nestedProp2','daily');
Javascript имеет функцию только для этого:массив.прототип.найти. Как пример
function isBigEnough(element) { return element >= 15; } [12, 5, 8, 130, 44].find(isBigEnough); // 130
это не трудно расширяет обратный вызов функции. Однако это не совместимо с IE (и частично с Edge). Для получения полного списка посмотрите на Совместимость С Браузерами