通过property的值从对象数组中获取JavaScript对象

use*_*368 694 javascript arrays

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

var jsObjects = [
   {a: 1, b: 2}, 
   {a: 3, b: 4}, 
   {a: 5, b: 6}, 
   {a: 7, b: 8}
];
Run Code Online (Sandbox Code Playgroud)

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

elc*_*nrs 1000

Filter 对象数组,其属性与value匹配,返回数组:

var result = jsObjects.filter(obj => {
  return obj.b === 6
})
Run Code Online (Sandbox Code Playgroud)

请参阅Array.prototype.filter上MDN Docs()

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)
Run Code Online (Sandbox Code Playgroud)

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

var result = jsObjects.find(obj => {
  return obj.b === 6
})
Run Code Online (Sandbox Code Playgroud)

请参阅Array.prototype.find()上MDN Docs

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)
Run Code Online (Sandbox Code Playgroud)

  • 这将返回一个数组 (104认同)
  • @nickf.我认为应该,如果有更多具有相同属性的对象会怎么样?否则:`result [0]`将是这种情况下的第一个(唯一)对象. (38认同)
  • 让它返回第一个很容易.添加"[0]"到最后.#javaScriptIsAwesome!var result = jsObjects.filter(function(obj){return obj.b == 6;})[0]; (25认同)
  • 问题是"获取JavaScript*object*",而不是"对象数组". (21认同)
  • @Gothdo是对的.要获取对象,我们可以使用Array.find:var result = jsObjects.find(function(obj){return obj.b === 6;}); (19认同)
  • 值得一提的是,"filter"仅在现代浏览器(即IE9及更高版本)中得到支持,因为它是ES5的一部分.因此,如果您想支持较旧的浏览器,您可能希望依赖于建议的其他方法之一. (7认同)
  • 是的,我想这取决于需要什么.如果它只是一个项目,我认为`filter`不是一个很好的选择,因为它将首先创建一个新的不需要的对象,其次它将继续遍历整个数组,即使找到该对象. (2认同)

Mic*_*ski 273

jsObjects.find(x => x.b === 6)
Run Code Online (Sandbox Code Playgroud)

来自MDN:

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


旁注:find()旧浏览器(如IE)不支持类似和箭头功能的方法,因此如果您想支持这些浏览器,则应使用Babel来转换代码.

  • @ 29er是的,我写道"所有浏览器都不支持"find()`和箭头函数等方法". (26认同)
  • 请注意,IE不支持此功能 (5认同)
  • 如果要修改原始数组中的对象,这是最佳选项.`filter()`返回对象的副本,_not_原始对象,因此更改不会反映在原始数组中 (4认同)
  • @thdoan OP要求"对象",而不是"匹配对象的数组".elclanrs的回答是错误的. (3认同)
  • 赞成,因为 IE 不支持。是时候继续前进了,我正是因为这个原因才使用它。 (2认同)

Rob*_*obG 141

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

对于循环:

function getByValue(arr, value) {

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

    if (arr[i].b == value) return arr[i];
  }
}
Run Code Online (Sandbox Code Playgroud)

.过滤

function getByValue2(arr, value) {

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

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

}
Run Code Online (Sandbox Code Playgroud)

.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

}
Run Code Online (Sandbox Code Playgroud)

另一方面,如果您确实想要...而想要查找具有值为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;
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 哪一个是最快的? (16认同)
  • Foor循环是迄今为止最快的方法(https://jsperf.com/extract-props/1). (5认同)
  • 用es6和以后使用:for(让arr的值) (2认同)
  • @RobG 将 `arr.length` 存储在 `iLen` 中而不是直接在 for 条件中使用 `arr.length` 作为 `i&lt;arr.length` 的任何具体原因? (2认同)

Roh*_*dal 35

尝试使用Array过滤方法过滤array of objects使用property.

var jsObjects = [
   {a: 1, b: 2}, 
   {a: 3, b: 4}, 
   {a: 5, b: 6}, 
   {a: 7, b: 8}
];
Run Code Online (Sandbox Code Playgroud)

使用数组过滤方法:

var filterObj = jsObjects.filter(function(e) {
  return e.b == 6;
});
Run Code Online (Sandbox Code Playgroud)

用于循环:

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

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


Ali*_*eza 22

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

使用时要小心find,因为即使IE11也不支持它,所以需要进行转换...

所以你有这个对象,如你所说:

var jsObjects = [
   {a: 1, b: 2}, 
   {a: 3, b: 4}, 
   {a: 5, b: 6}, 
   {a: 7, b: 8}
];
Run Code Online (Sandbox Code Playgroud)

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

function filterValue(obj, key, value) {
  return obj.find(function(v){ return v[key] === value});
}
Run Code Online (Sandbox Code Playgroud)

并使用这样的功能:

filterValue(jsObjects, "b", 6); //{a: 5, b: 6}
Run Code Online (Sandbox Code Playgroud)

ES6中甚至缩短版本:

const filterValue = (obj, key, value)=> obj.find(v => v[key] === value);
Run Code Online (Sandbox Code Playgroud)

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

const filterValue = (obj, key, value)=> obj.filter(v => v[key] === value);
Run Code Online (Sandbox Code Playgroud)

我们会回来[{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;
}
Run Code Online (Sandbox Code Playgroud)

并称之为:

filteredArray(jsObjects, "b", 6); //[{a: 5, b: 6}]
Run Code Online (Sandbox Code Playgroud)

  • 谢谢@Alireza。非常完整的答案。至于 .filter 部分: &lt; 此方法将返回一个数组......不是最优雅的解决方案,但考虑在最后添加 [0] 以快速修复。const filterValue = (obj, key, value)=&gt; obj.filter(v =&gt; v[key] === value)[0]; (2认同)

mai*_*aia 20

使用underscore.js:

var foundObject = _.findWhere(jsObjects, {b: 6});
Run Code Online (Sandbox Code Playgroud)


Ami*_*mir 18

看起来在ECMAScript 6提案中有Array方法find()findIndex().MDN还提供了polyfill,您可以包含这些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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)


nic*_*ckf 15

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

var found;
jsObjects.some(function (obj) {
  if (obj.b === 6) {
    found = obj;
    return true;
  }
});
Run Code Online (Sandbox Code Playgroud)

或者,如果您使用下划线:

var found = _.select(jsObjects, function (obj) {
  return obj.b === 6;
});
Run Code Online (Sandbox Code Playgroud)

  • @RobG是的,很清楚.请注意我是如何从中分配值的?:)它只是在这里用作一种短路循环的方法. (6认同)
  • [`some`](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.17)只返回true或false,它不返回匹配对象. (3认同)

Sam*_*hay 14

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

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

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


小智 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}
Run Code Online (Sandbox Code Playgroud)


Sim*_*ion 9

如何使用_.find(collection, [predicate=_.identity], [fromIndex=0])LO-冲刺获得由对象的属性值数组对象的对象.你可以这样做:

var o = _.find(jsObjects, {'b': 6});
Run Code Online (Sandbox Code Playgroud)

参数:

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

返回

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

在性能方面,_.find()速度更快,因为它只用属性拉第一个对象,{'b': 6}另一方面,如果假设你的数组包含多个具有匹配属性集(key:value)的对象,那么你应该考虑使用_.filter()方法.所以在你的情况下,因为你的数组有一个具有此属性的对象,我会使用_.find().


asr*_*oel 5

请参阅此文档https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_objects/Object/values
示例:

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 }
Run Code Online (Sandbox Code Playgroud)

  • 不清楚这如何与您正在调用的 'find()' 方法配合使用。此外,Internet Explorer 不支持 Object.values()。 (3认同)

小智 5

var result = jsObjects.filter(x=> x.b === 6);
Run Code Online (Sandbox Code Playgroud)

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


And*_*rew 5

刚刚改进了此答案中最快/最好的部分,使其更加可重用/清晰:

function getElByPropVal(arr, prop, val){
    for (var i = 0, length = arr.length; i < length; i++) {
        if (arr[i][prop] == val){
            return arr[i];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)