【问题标题】:Get JavaScript object from array of objects by value of property [duplicate]通过属性值从对象数组中获取JavaScript对象[重复]
【发布时间】:2012-12-07 11:59:58
【问题描述】:

假设我有一个包含四个对象的数组:

var jsObjects = [
   {a: 1, b: 2}, 
   {a: 3, b: 4}, 
   {a: 5, b: 6}, 
   {a: 7, b: 8}
];

有没有一种方法可以通过属性b 的值来获取第三个对象({a: 5, b: 6}),例如没有for...in 循环?

【问题讨论】:

  • 是的,这是可能的,只要 b 的值在数组中的所有对象中是唯一的(在本例中就是这样)
  • @undefined 很确定 op 想要在数组中搜索具有b = 6的对象
  • 我喜欢短小精悍并且兼容pre-ES6浏览器... jsObjects.find(function(x) {if(xb == 6) return x}) 你可以用它来抓取属性 a 同时... jsObjects.find(function(x) {if(xb == 6) return x}).a

标签: javascript arrays


【解决方案1】:

Filter对象数组,属性匹配值,返回数组:

var result = jsObjects.filter(obj => {
  return obj.b === 6
})

MDN Docs on Array.prototype.filter()

const jsObjects = [
  {a: 1, b: 2}, 
  {a: 3, b: 4}, 
  {a: 5, b: 6}, 
  {a: 7, b: 8}
]

let result = jsObjects.filter(obj => {
  return obj.b === 6
})

console.log(result)

Find数组中第一个元素/对象的值,否则返回undefined

var result = jsObjects.find(obj => {
  return obj.b === 6
})

MDN Docs on Array.prototype.find()

const jsObjects = [
  {a: 1, b: 2}, 
  {a: 3, b: 4}, 
  {a: 5, b: 6}, 
  {a: 7, b: 8}
]

let result = jsObjects.find(obj => {
  return obj.b === 6
})

console.log(result)

【讨论】:

  • 这将返回一个数组
  • @nickf。我认为应该,如果有更多具有相同属性的对象怎么办?否则:result[0] 在这种情况下将是第一个(唯一)对象。
  • 让它返回第一个很容易。在末尾添加“[0]”。 #javaScriptIsAwesome! var result = jsObjects.filter(function( obj ) { return obj.b == 6; })[0];
  • 问题是“获取 JavaScript object”,而不是“对象数组”。
  • @Gothdo 是对的。要获取对象,我们可以使用 Array.find: var result = jsObjects.find(function( obj ) { return obj.b === 6; });
【解决方案2】:
jsObjects.find(x => x.b === 6)

来自 MDN:

如果数组中的元素满足提供的测试函数,find() 方法将返回数组中的值。否则返回undefined


附注:旧版浏览器(如 IE)不支持 find() 和箭头函数等方法,因此如果您想支持这些浏览器,则应使用 Babel 转译您的代码。

【讨论】:

  • 注意IE不支持这个
  • @29er 是的,我写过“并非所有浏览器都支持find() 和箭头函数之类的方法”。
  • 如果要修改原始数组中的对象,这是最好的选择。 filter() 返回对象的副本,不是原始对象,因此更改不会反映在原始数组中
  • 这不完全等同于@elclanrs 使用filter() 的答案:它只返回第一个匹配项。
  • @thdoan OP 要求的是“对象”,而不是“匹配对象的数组”。 elclanrs 的回答是错误的。
【解决方案3】:

我不知道您为什么反对 for 循环(大概您的意思是 for loop,而不是专门的 for..in),它们快速且易于阅读。无论如何,这里有一些选项。

For 循环:

function getByValue(arr, value) {

  for (var i=0, iLen=arr.length; i<iLen; i++) {

    if (arr[i].b == value) return arr[i];
  }
}

.filter

function getByValue2(arr, value) {

  var result  = arr.filter(function(o){return o.b == value;} );

  return result? result[0] : null; // or undefined

}

.forEach

function getByValue3(arr, value) {

  var result = [];

  arr.forEach(function(o){if (o.b == value) result.push(o);} );

  return result? result[0] : null; // or undefined

}

另一方面,如果您确实是指 for..in 并且想要查找任何属性值为 6 的对象,那么您必须使用 for..in 除非您将名称传递给检查。

示例

function getByValue4(arr, value) {
  var o;

  for (var i=0, iLen=arr.length; i<iLen; i++) {
    o = arr[i];

    for (var p in o) {
      if (o.hasOwnProperty(p) && o[p] == value) {
        return o;
      }
    }
  }
}

【讨论】:

  • 哪一个是最快的?
  • Foor loop 是迄今为止最快的方法 (jsperf.com/extract-props/1)。
  • 在 es6 及以后使用:for(let value of arr)
  • @RobG 是否有任何特定理由将arr.length 存储在iLen 中,而不是在for 条件中直接使用arr.length 作为i&lt;arr.length
  • @VikasPrasad — 只是一个小的性能增强,现在可能没有帮助,但在早期它确实有帮助。
【解决方案4】:

尝试使用Array filter 方法过滤array of objectsproperty

var jsObjects = [
   {a: 1, b: 2}, 
   {a: 3, b: 4}, 
   {a: 5, b: 6}, 
   {a: 7, b: 8}
];

使用数组过滤方法:

var filterObj = jsObjects.filter(function(e) {
  return e.b == 6;
});

在循环中使用:

for (var i in jsObjects) {
  if (jsObjects[i].b == 6) {
    console.log(jsObjects[i]); // {a: 5, b: 6}
  }
}

工作小提琴: https://jsfiddle.net/uq9n9g77/

【讨论】:

    【解决方案5】:

    好的,有几种方法可以做到这一点,但让我们从最简单和最新的方法开始,这个函数称为find()

    当你使用find时要小心,因为即使IE11不支持它,所以它需要被转译......

    所以你有你说的这个对象:

    var jsObjects = [
       {a: 1, b: 2}, 
       {a: 3, b: 4}, 
       {a: 5, b: 6}, 
       {a: 7, b: 8}
    ];
    

    你可以编写一个函数并像这样得到它:

    function filterValue(obj, key, value) {
      return obj.find(function(v){ return v[key] === value});
    }
    

    并像这样使用函数:

    filterValue(jsObjects, "b", 6); //{a: 5, b: 6}
    

    ES6 中也有更短的版本:

    const filterValue = (obj, key, value)=> obj.find(v => v[key] === value);
    

    此方法只返回第一个匹配的值...,为了更好的结果和浏览器支持,您可以使用filter

    const filterValue = (obj, key, value)=> obj.filter(v => v[key] === value);
    

    我们将返回[{a: 5, b: 6}]...

    此方法将返回一个数组而不是...

    你也可以简单地使用 for 循环,创建一个这样的函数:

    function filteredArray(arr, key, value) {
      const newArray = [];
      for(i=0, l=arr.length; i<l; i++) {
        if(arr[i][key] === value) {
          newArray.push(arr[i]);
        }
      }
     return newArray;
    }
    

    然后这样称呼它:

    filteredArray(jsObjects, "b", 6); //[{a: 5, b: 6}]
    

    【讨论】:

    • 谢谢@Alireza。非常完整的答案。至于 .filter 部分: obj.filter(v => v[key] === value)[0];
    【解决方案6】:

    请参阅此文档Array.prototype.find()

    示例:

    var inventory = [
        {name: 'apples', quantity: 2},
        {name: 'bananas', quantity: 0},
        {name: 'cherries', quantity: 5}
    ];
    
    function findCherries(fruit) { 
        return fruit.name === 'cherries';
    }
    
    console.log(inventory.find(findCherries)); 
    // { name: 'cherries', quantity: 5 }
    

    【讨论】:

    • 不清楚这如何与您调用的“find()”方法一起工作。此外,Internet Explorer 不支持 Object.values()。
    • 好像链接错了。作者大概打算这个:Array.prototype.find()
    • 如果什么也没找到会返回什么? undefined?
    • @OliverDixon 是的。
    【解决方案7】:

    使用 underscore.js:

    var foundObject = _.findWhere(jsObjects, {b: 6});
    

    【讨论】:

    【解决方案8】:

    看起来在 ECMAScript 6 提案中有 Array 方法 find()findIndex()。 MDN 还提供了 polyfill,您可以将其包含在所有浏览器中以获取这些功能。

    find():

    function isPrime(element, index, array) {
        var start = 2;
        while (start <= Math.sqrt(element)) {
            if (element % start++ < 1) return false;
        }
        return (element > 1);
    }
    
    console.log( [4, 6, 8, 12].find(isPrime) ); // undefined, not found
    console.log( [4, 5, 8, 12].find(isPrime) ); // 5
    

    findIndex():

    function isPrime(element, index, array) {
        var start = 2;
        while (start <= Math.sqrt(element)) {
            if (element % start++ < 1) return false;
        }
        return (element > 1);
    }
    
    console.log( [4, 6, 8, 12].findIndex(isPrime) ); // -1, not found
    console.log( [4, 6, 7, 12].findIndex(isPrime) ); // 2
    

    【讨论】:

    • 我在寻找给你索引的版本。谢谢!
    【解决方案9】:

    如果我理解正确,您想在数组中找到b 属性为6 的对象?

    var found;
    jsObjects.some(function (obj) {
      if (obj.b === 6) {
        found = obj;
        return true;
      }
    });
    

    或者如果您使用下划线:

    var found = _.select(jsObjects, function (obj) {
      return obj.b === 6;
    });
    

    【讨论】:

    • some 只返回真假,不返回匹配对象。
    • @RobG 是的,很清楚。请注意我如何不从中分配值? :) 它只是在这里被用作短路循环的一种方式。
    • 过于复杂。 .some() 用于确定数组中的某些元素是否通过测试。在这种情况下,最好使用.forEach(),因为您已经决定将结果分配给一个变量。
    • @Gothdo 为什么在已经得到结果的情况下还要继续循环遍历数组? .some 中的 return true 本质上类似于 for 循环中的 break
    【解决方案10】:

    如果您正在寻找单个结果而不是数组,我可以建议减少吗?

    这是一个简单的 'ole javascript 解决方案,如果存在则返回匹配的对象,否则返回 null。

    var result = arr.reduce(function(prev, curr) { return (curr.b === 6) ? curr : prev; }, null);
    

    【讨论】:

      【解决方案11】:

      您可以将它与箭头功能一起使用,如下所示:

      var demoArray = [
         {name: 'apples', quantity: 2},
         {name: 'bananas', quantity: 0},
         {name: 'cherries', quantity: 5}
      ];
      
      var result = demoArray.filter( obj => obj.name === 'apples')[0];
      console.log(result);
      // {name: 'apples', quantity: 2}
      

      【讨论】:

        【解决方案12】:

        如何使用lo-dash_.find(collection, [predicate=_.identity], [fromIndex=0]) 通过对象属性值从对象数组中获取对象。你可以这样做:

        var o = _.find(jsObjects, {'b': 6});
        

        参数:

        collection (Array|Object): The collection to inspect.
        [predicate=_.identity] (Function): The function invoked per iteration.
        [fromIndex=0] (number): The index to search from.
        

        返回

        (*): Returns the matched element (in your case, {a: 5, b: 6}), else undefined.
        

        在性能方面,_.find() 更快,因为它只提取具有属性{'b': 6} 的第一个对象,另一方面,如果假设您的数组包含多个具有匹配属性集(键:值)的对象,那么你应该考虑使用_.filter() 方法。因此,在您的情况下,由于您的数组有一个具有此属性的对象,我将使用_.find()

        【讨论】:

          【解决方案13】:

          使this answer 中最好/最快的部分更易于重复使用和清晰:

          function getElByPropVal(myArray, prop, val){
              for (var i = 0, length = myArray.length; i < length; i++) {
                  if (myArray[i][prop] == val){
                      return myArray[i];
                  }
              }
          }
          

          【讨论】:

            【解决方案14】:
            var result = jsObjects.filter(x=> x.b === 6);
            

            会更好,在过滤器中使用 return 有时你不能得到结果(我不知道为什么)

            【讨论】:

              【解决方案15】:

              通过特定属性值从对象数组中获取第一个对象:

              function getObjectFromObjectsArrayByPropertyValue(objectsArray, propertyName, propertyValue) {
                return objectsArray.find(function (objectsArrayElement) {
                  return objectsArrayElement[propertyName] == propertyValue;
                });
              }
              
              function findObject () {
                var arrayOfObjectsString = document.getElementById("arrayOfObjects").value,
                    arrayOfObjects,
                    propertyName = document.getElementById("propertyName").value,
                    propertyValue = document.getElementById("propertyValue").value,
                    preview = document.getElementById("preview"),
                    searchingObject;
                
                arrayOfObjects = JSON.parse(arrayOfObjectsString);
                
                console.debug(arrayOfObjects);
                
                if(arrayOfObjects && propertyName && propertyValue) {
                  searchingObject = getObjectFromObjectsArrayByPropertyValue(arrayOfObjects, propertyName, propertyValue);
                  if(searchingObject) {
                    preview.innerHTML = JSON.stringify(searchingObject, false, 2);
                  } else {
                    preview.innerHTML = "there is no object with property " + propertyName + " = " + propertyValue + " in your array of objects";
                  }
                }
              }
              pre {
                padding: 5px;
                border-radius: 4px;
                background: #f3f2f2;
              }
              
              textarea, button {
                width: 100%
              }
              <fieldset>
                <legend>Input Data:</legend>
                <label>Put here your array of objects</label>
                <textarea rows="7" id="arrayOfObjects">
                [
                  {"a": 1, "b": 2},
                  {"a": 3, "b": 4},
                  {"a": 5, "b": 6},
                  {"a": 7, "b": 8, "c": 157}
                ]
                </textarea>
              
                <hr>
              
                <label>property name: </label> <input type="text" id="propertyName"  value="b"/>
                <label>property value: </label> <input type="text" id="propertyValue" value=6 />
                   
              </fieldset>
              <hr>
              <button onclick="findObject()">find object in array!</button>
              <hr>
              <fieldset>
                <legend>Searching Result:</legend>
                <pre id="preview">click find</pre>
              </fieldset>

              【讨论】:

                【解决方案16】:

                使用 find 和 bind 将特定的键值传递给回调函数。

                   function byValue(o) { 
                       return o.a === this.a && o.b === this.b; 
                   };   
                
                   var result = jsObjects.find(byValue.bind({ a: 5, b: 6 }));
                

                【讨论】:

                  【解决方案17】:
                  var jsObjects = [{a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}, {a: 7, b: 8}];
                  

                  要访问第三个对象,请使用:jsObjects[2];
                  要访问第三个对象 b 值,请使用:jsObjects[2].b;

                  【讨论】:

                    猜你喜欢
                    • 2021-01-15
                    • 2018-08-30
                    • 2019-05-29
                    • 2014-09-03
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-06-10
                    相关资源
                    最近更新 更多