Jquery how to find an Object by attribute in an Array

江枫思渺然 提交于 2019-12-17 10:22:10

问题


Given I have an array of "purpose" objects:

//array of purpose objects:
var purposeObjects = [
    {purpose: "daily"},
    {purpose: "weekly"},
    {purpose: "monthly"}
];

(for simplicity i am omitting other attributes)

Now I want to have a method that returns a specific one of the objects if a matching purpose name is found.

This is not working:

function findPurpose(purposeName){
    return $.grep(purposeObjects, function(){
      return this.purpose == purposeName;
    });
};

findPurpose("daily");

but it actually returns an empty array:

[]

I am using JQuery 1.5.2. I have also tried with $.each() but with no luck. Apparently, most JQuery methods are designed for usage with DOM elements (such as filter().

Any ideas on how to achieve this?


回答1:


ES6

    array.find((o) => { return o[propertyName] === propertyValue })

More about the find method here.

ES5

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
}

Note

jQuery $.grep (or other filtering function) is not the optimal solution.

The $.grep function will loop through all the elements of the array, even if the searched object has been already found during the loop. From jQuery grep documentation :

The $.grep() method removes items from an array as necessary so that all remaining items pass a provided test. The test is a function that is passed an array item and the index of the item within the array. Only if the test returns true will the item be in the result array.




回答2:


you should pass reference on item in grep function:

function findPurpose(purposeName){
    return $.grep(purposeObjects, function(item){
      return item.purpose == purposeName;
    });
};

Example




回答3:


I personally use a more generic function that works for any property of any array:

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];
}

You just call it like this:

lookup(purposeObjects, "purpose", "daily");



回答4:


The error was that you cannot use this in the grep, but you must use a reference to the element. This works:

function findPurpose(purposeName){
    return $.grep(purposeObjects, function(n, i){
      return n.purpose == purposeName;
    });
};

findPurpose("daily");

returns:

[Object { purpose="daily"}]



回答5:


Use the Underscore.js findWhere function (http://underscorejs.org/#findWhere):

var purposeObjects = [
    {purpose: "daily"},
    {purpose: "weekly"},
    {purpose: "monthly"}
];

var daily = _.findWhere(purposeObjects, {purpose: 'daily'});

daily would equal:

{"purpose":"daily"}

Here's a fiddle: http://jsfiddle.net/spencerw/oqbgc21x/

To return more than one (if you had more in your array) you could use _.where(...)




回答6:


Best, Fastest way is

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;
}



回答7:


If your array is actually a set of JQuery objects, what about simply using the .filter() method ?

purposeObjects.filter('[purpose="daily"]')



回答8:


One more solution:

function firstOrNull(array, expr) {
  for (var i = 0; i < array.length; i++) {
    if (expr(array[i]))
      return array[i];
    }
  return null;
}

Using: firstOrNull([{ a: 1, b: 2 }, { a: 3, b: 3 }], function(item) { return item.a === 3; });

This function don't executes for each element from the array (it's valuable for large arrays)




回答9:


I have created a util service for my angular application. It have two function which use very often.

For example you have object.

First getting value from object recursively without throwing undefined error.

{prop: { nestedProp1: {nestedProp2: somevalue}}}; get nestedProp2 2 without undefined checks.

Second filter array on basis

[{prop: { nestedProp1: {nestedProp2: somevalue1}}}, {prop: { nestedProp1: {nestedProp2: somevalue2}}}];

Find object from array with 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;
}});

For solution for current question. inject UtilService and call,

UtilService.arrayPropFilter(purposeArray,'purpose','daily');

Or more advanced

UtilService.arrayPropFilter(purposeArray,'purpose.nestedProp1.nestedProp2','daily');



回答10:


Javascript has a function just for that: Array.prototype.find. As example

function isBigEnough(element) {
  return element >= 15;
}

[12, 5, 8, 130, 44].find(isBigEnough); // 130

It not difficult to extends the callback to a function. However this is not compatible with IE (and partially with Edge). For a full list look at the Browser Compatibility




回答11:


copied from polyfill Array.prototype.find code of Array.find, and added the array as first parameter.

you can pass the search term as predicate function

// Example
var listOfObjects = [{key: "1", value: "one"}, {key: "2", value: "two"}]
var result = findInArray(listOfObjects, function(element) {
  return element.key == "1";
});
console.log(result);

// the function you want
function findInArray(listOfObjects, predicate) {
      if (listOfObjects == null) {
        throw new TypeError('listOfObjects is null or not defined');
      }

      var o = Object(listOfObjects);

      var len = o.length >>> 0;

      if (typeof predicate !== 'function') {
        throw new TypeError('predicate must be a function');
      }

      var thisArg = arguments[1];

      var k = 0;

      while (k < len) {
        var kValue = o[k];
        if (predicate.call(thisArg, kValue, k, o)) {
          return kValue;
        }
        k++;
      }

      return undefined;
}


来源:https://stackoverflow.com/questions/5579678/jquery-how-to-find-an-object-by-attribute-in-an-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!