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 61

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). Для получения полного списка посмотрите на Совместимость С Браузерами