ChatGPT解决这个技术问题 Extra ChatGPT

Get JavaScript object from array of objects by value of property [duplicate]

This question already has answers here: Find object by id in an array of JavaScript objects (36 answers) Closed 4 years ago.

Let's say I have an array of four objects:

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

Is there a way that I can get the third object ({a: 5, b: 6}) by the value of the property b for example without a for...in loop?

Yes, it is possible, as long as the value of b is unique among all of the objects in your array (which it is in this example)
@undefined Pretty sure op wants to search the array for at the object having b = 6
I like short & sweet and compatible with pre-ES6 browsers... jsObjects.find(function(x) {if(x.b == 6) return x}) You can use it to grab the property a at the same time... jsObjects.find(function(x) {if(x.b == 6) return x}).a

A
Alireza

Filter array of objects, which property matches value, returns array:

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

See the 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 the value of the first element/object in the array, otherwise undefined is returned.

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

See the 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)


This will return an array
@nickf. I think it should, what if there are more objects with same properties? Otherwise: result[0] will be the first (unique) object in this case.
To have it return just the first is easy. Add "[0]" to the end. #javaScriptIsAwesome! var result = jsObjects.filter(function( obj ) { return obj.b == 6; })[0];
The question is "get JavaScript object", not "array of objects".
@Gothdo is right. To get object we can use Array.find: var result = jsObjects.find(function( obj ) { return obj.b === 6; });
M
Michał Perłakowski
jsObjects.find(x => x.b === 6)

From MDN:

The find() method returns a value in the array, if an element in the array satisfies the provided testing function. Otherwise undefined is returned.

Side note: methods like find() and arrow functions are not supported by older browsers (like IE), so if you want to support these browsers, you should transpile your code using Babel.


Note that this is not supported in IE
@29er Yes, I wrote that "methods like find() and arrow functions are not supported by all browsers".
This is the best option if you want to modify the object in the original array. filter() returns a copy of the object, not the original object, so changes will not be reflected in the original array
This is not exactly equivalent to @elclanrs's answer using filter(): it returns only the first match.
@thdoan The OP asked for "the object", not "an array of matching objects". elclanrs's answer is wrong.
A
Aryan

I don't know why you are against a for loop (presumably you meant a for loop, not specifically for..in), they are fast and easy to read. Anyhow, here's some options.

For loop:

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

}

If, on the other hand you really did mean for..in and want to find an object with any property with a value of 6, then you must use for..in unless you pass the names to check.

Example

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

which one is the fastest one?
Foor loop by far the fastest method (jsperf.com/extract-props/1).
with es6 and later use: for(let value of arr)
@RobG any specific reason to store arr.length in iLen instead of directly using arr.length in the for condition as i<arr.length?
@VikasPrasad—just a minor performance enhancement, probably doesn't help now but in the early days it did.
R
Rohìt Jíndal

Ways to achieve the requirement :

Using Array.find() method :

const jsObject = [ {a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}, {a: 7, b: 8} ]; const filteredResult = jsObject.find((e) => e.b == 6); console.log(filteredResult);

Using Array.filter() method :

const jsObjects = [ {a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}, {a: 7, b: 8} ]; const filterObj = jsObjects.filter((e) => e.b == 6); console.log(filterObj[0]);

Using for...in loop :

const jsObjects = [ {a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}, {a: 7, b: 8} ]; for (const i in jsObjects) { if (jsObjects[i].b == 6) { console.log(jsObjects[i]); } }


A
Alireza

OK, there are few ways to do that, but let's start with the simplest one and latest approach to do this, this function is called find().

Just be careful when you using find to as even IE11 dosn't support it, so it needs to be transpiled...

so you have this object as you said:

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

and you can write a function and get it like this:

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

and use the function like this:

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

Also in ES6 for even shortened version:

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

This method only return the first value which match..., for better result and browser support, you can use filter:

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

and we will return [{a: 5, b: 6}]...

This method will return an array instead...

You simpley use for loop as well, create a function like this:

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

and call it like this:

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

Thanks @Alireza. Very complete answer. As for the .filter part: < This method will return an array instead... Not the most elegant solution, but consider adding [0] at the end, for a quick fix. const filterValue = (obj, key, value)=> obj.filter(v => v[key] === value)[0];
M
Megha Karabylu Balaraju

See this documentation Array.prototype.find()

Example:

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 }

Not clear how this works with the 'find()' method you're calling. Additionally Object.values() is not supported in Internet Explorer.
It seems that the link is mistaken. The author probably intended this one: Array.prototype.find()
What does this return if it doesn't find anything? undefined?
@OliverDixon yes.
m
maia

Using underscore.js:

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

Deprecated. Use _.find instead: stackoverflow.com/a/40958199/12695188
M
Michał Perłakowski

It looks like in the ECMAScript 6 proposal there are the Array methods find() and findIndex(). MDN also offers polyfills which you can include to get the functionality of these across all browsers.

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

n
nickf

If I understand correctly, you want to find the object in the array whose b property is 6?

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

Or if you were using underscore:

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

some just returns true or false, it doesn't return the matching object.
@RobG yep, well aware. Note how I'm not assigning the value from it? :) It's just being used here as a way to short-circuit the loop.
Overcomplicated. .some() is meant to determine whether some element in the array passes the test. In this case it would be better to use .forEach(), since you already decided to assign the result to a variable.
@Gothdo why would you continue looping through the array when you already have the result? The return true in a .some is essentially like a break in a for loop.
S
Sam Dushay

If you are looking for a single result, rather than an array, may I suggest reduce?

Here is a solution in plain 'ole javascript that returns a matching object if one exists, or null if not.

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

S
Shobhit Sharma

You can use it with the arrow function as well like as below :

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}

S
Simple-Solution

How about using _.find(collection, [predicate=_.identity], [fromIndex=0]) of lo-dash to get object from array of objects by object property value. You could do something like this:

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

Arguments:

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

Returns

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

In terms of performance, _.find() is faster as it only pulls the first object with property {'b': 6}, on the other hand, if suppose your array contains multiple objects with matching set of properties (key:value), then you should consider using _.filter() method. So in your case, as your array has a single object with this property, I would use _.find().


A
Andrew

Made the best/fastest part of this answer more re-usable & clear:

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

D
Died
var result = jsObjects.filter(x=> x.b === 6);

will be better, using return in filter sometimes you can't get result (I dunno why)


k
kolodi

To get first object from array of objects by a specific property value:

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% }

Input Data:


Searching Result:
click find


S
Serjuice

Using find with bind to pass specific key values to a callback function.

   function byValue(o) { 
       return o.a === this.a && o.b === this.b; 
   };   

   var result = jsObjects.find(byValue.bind({ a: 5, b: 6 }));

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

to access the third object, use: jsObjects[2];
to access the third object b value, use: jsObjects[2].b;