问题
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