Jquery如何在Array中按属性查找Object

时间:2011-04-07 10:32:33

标签: jquery collections filter traversal

鉴于我有一系列“目的”对象:

//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()

)而设计的

关于如何实现这一目标的任何想法?

11 个答案:

答案 0 :(得分:77)

ES6

const getObjectByPropertyValue = function(array, propertyName, propertyValue) {
    return array.find((o) => { return o[propertyName] === propertyValue })
}

// Your specific case: getObjectByValue(purposeObjects, "purpose", "weekly") => {purpose: "weekly"}

从ES6开始,JavaScript Array原型有一个find方法,它返回数组中第一个满足提供的测试函数的元素的值。否则返回undefined。

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
}

注意

jQuery $ .grep(或其他过滤功能)不是最佳解决方案。

$.grep函数将循环遍历所有数组元素,即使在循环期间已找到搜索到的对象也是如此。来自jQuery grep文档:

  

$ .grep()方法根据需要从数组中删除项目   所有剩余的项目都通过了提供的测试测试是一个功能   传递数组项和数组中项的索引。   只有当测试返回true时,该项才会在结果数组中。

答案 1 :(得分:37)

你应该在grep函数中传递对项目的引用:

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

Example

答案 2 :(得分:29)

我个人使用更通用的函数,适用于任何数组的任何属性:

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");

答案 3 :(得分:26)

错误是您无法在grep中使用this,但必须使用对该元素的引用。这有效:

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

findPurpose("daily");

返回:

[Object { purpose="daily"}]

答案 4 :(得分:5)

使用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(...)

答案 5 :(得分:4)

最好,最快的方式是

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

答案 6 :(得分:3)

如果您的数组实际上是一组JQuery对象,那么仅使用.filter()方法呢?

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

答案 7 :(得分:1)

还有一个解决方案:

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

这个函数不会对数组中的每个元素执行(它对大数组很有用)

答案 8 :(得分:0)

我为我的角度应用程序创建了一个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');

答案 9 :(得分:0)

Javascript只有一个功能:Array.prototype.find。例如

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

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

将回调扩展到函数并不困难。但是这与IE不兼容(部分与Edge兼容)。有关完整列表,请查看Browser Compatibility

答案 10 :(得分:0)

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