【问题标题】:Jquery how to find an Object by attribute in an ArrayJquery如何通过数组中的属性查找对象
【发布时间】:2011-07-31 13:59:26
【问题描述】:

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

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

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

【问题讨论】:

    标签: jquery collections filter traversal


    【解决方案1】:

    不需要 jQuery。

    JavaScript 数组有一个 find 方法,因此您可以在一行中实现:

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

    示例

    
    const purposeObjects = [
        {purpose: "daily"},
        {purpose: "weekly"},
        {purpose: "monthly"}
    ];
    
    purposeObjects.find((o) => { return o["purpose"] === "weekly" })      
    
    // output -> {purpose: "weekly"}
    

    如果您需要 IE 兼容性,请在您的代码中导入此 polyfill

    【讨论】:

    • 我认为 if ( purposeObjects[i]. purposeName === purposeName) 应该读 if ( purposeObjects[i]. purpose === purposeName)
    • 这是最好的解决方案!!你摇滚朋友
    【解决方案2】:

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

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

    Example

    【讨论】:

    • 没错!这正是我最终要做的。
    • $.grep 函数将循环遍历数组的所有元素,即使在循环期间已经找到了搜索的对象。这不是最优的。看看我的回答。
    • 完全同意 Luca 的观点:$.grep() 循环遍历整个对象,即使您在条件中返回!在较小的对象中,这可能并不重要,但如果对象真的很大,比如到 2034 年的日历呢?我会选择 Luca Fagioli 的解决方案作为最佳答案
    【解决方案3】:

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

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

    【讨论】:

    • 某些情况会阻止它 100% 的工作。我有一些依赖于这种方法的方法——通过某种方法调用,它总是有效,而其他方法永远不会有效。我正在记录所有通话,看不到从“有效”到“无效”的明显区别。此输出显示第三次迭代应该满足测试并返回 3.true array[i][prop]: 19741 val: 19741
    【解决方案4】:

    错误是你不能在 grep 中使用this,但你必须使用对元素的引用。这有效:

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

    返回:

    [Object { purpose="daily"}]
    

    【讨论】:

    • $.grep 函数将循环遍历数组的所有元素,即使在循环期间已经找到了搜索的对象。这不是最优的。看看我的回答。
    • 完全同意 Luca 的观点:$.grep() 循环遍历整个对象,即使您在条件中返回!在较小的对象中,这可能并不重要,但如果对象真的很大,比如到 2034 年的日历呢?我会选择 Luca Fagioli 的解决方案作为最佳答案
    【解决方案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(...)

    【讨论】:

      【解决方案6】:

      最好,最快的方法是

      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】:

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

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

        【讨论】:

          【解决方案8】:

          另一种解决方案:

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

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

          【讨论】:

            【解决方案9】:

            我为我的 Angular 应用程序创建了一个实用服务。它有两个经常使用的功能。

            例如你有对象。

            首先递归地从对象中获取值而不抛出未定义的错误。

            {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');
            

            【讨论】:

              【解决方案10】:

              Javascript 有一个专门的功能:Array.prototype.find。举例

              function isBigEnough(element) {
                return element >= 15;
              }
              
              [12, 5, 8, 130, 44].find(isBigEnough); // 130
              

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

              【讨论】:

                【解决方案11】:

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2022-08-24
                  • 2016-07-26
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-07-05
                  • 2016-09-19
                  • 1970-01-01
                  相关资源
                  最近更新 更多