通过属性值从对象数组中获取JavaScript对象[重复]

Posted

技术标签:

【中文标题】通过属性值从对象数组中获取JavaScript对象[重复]【英文标题】:Get JavaScript object from array of objects by value of property [duplicate] 【发布时间】: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 的对象 相关:Find an object by property value in an array of javascript objects 我喜欢短小精悍并且兼容 pre-ES6 浏览器... jsObjects.find(function(x) if(xb == 6) return x) 你可以用它来抓取属性 a 同时... jsObjects.find(function(x) if(xb == 6) return x).a 【参考方案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);

【讨论】:

已弃用。请改用_.find:***.com/a/40958199/12695188【参考方案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;

【讨论】:

以上是关于通过属性值从对象数组中获取JavaScript对象[重复]的主要内容,如果未能解决你的问题,请参考以下文章

根据JavaScript中的属性值从对象数组中选择[重复]

根据值从对象数组中选择一个属性:Javascript

使用JavaScript函数从数组中获取单个对象[重复]

javascript 通过对象数组中的属性值获取不同的对象

通过选择多个属性值之一从数组中获取 JavaScript 对象 [关闭]

TypeScript - 根据属性值从数组中取出对象