通过属性值从对象数组中获取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<arr.length
?
@VikasPrasad — 只是一个小的性能增强,现在可能没有帮助,但在早期它确实有帮助。【参考方案4】:
尝试使用Array filter 方法过滤array of objects
和property
。
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对象[重复]的主要内容,如果未能解决你的问题,请参考以下文章