鉴于我有一系列“目的”对象:
//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。我也试过$ .each()但没有运气。显然,大多数JQuery方法都是为DOM元素(如filter()
)而设计的。
关于如何实现这一点的任何想法?
array.find((o) => { return o[propertyName] === propertyValue })
更多关于find
方法here。
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 $ .grep(或其他过滤函数)不是最佳解决方案。
$.grep
函数将循环遍历数组的所有元素,即使在循环期间已找到搜索的对象。从jQuery grep文档:
$ .grep()方法根据需要从数组中删除项目,以便所有剩余项目都通过提供的测试。测试是一个传递数组项的函数和数组中项的索引。仅当测试返回true时,该项才会位于结果数组中。
Javascript只有一个功能:Array.prototype.find。例如
function isBigEnough(element) {
return element >= 15;
}
[12, 5, 8, 130, 44].find(isBigEnough); // 130
将回调扩展到函数并不困难。但是这与IE不兼容(部分与Edge兼容)。如需查看完整列表,请查看Browser Compatibility
从Array.find的polyfill Array.prototype.find代码复制,并将该数组添加为第一个参数。
您可以将搜索词作为谓词函数传递
// 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;
}
你应该在grep函数中传递项目的引用:
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");
错误是你不能在grep中使用this
,但你必须使用对元素的引用。这有效:
function findPurpose(purposeName){
return $.grep(purposeObjects, function(n, i){
return n.purpose == purposeName;
});
};
findPurpose("daily");
收益:
[Object { purpose="daily"}]
使用Underscore.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');