1282

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?

dreftymac
  • 31,404
  • 26
  • 119
  • 182
user765368
  • 19,590
  • 27
  • 96
  • 167
  • 1
    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) – Will C. Dec 20 '12 at 01:58
  • @undefined Pretty sure op wants to search the array for at the object having `b = 6` – Madbreaks Dec 20 '12 at 01:59
  • Related: [Find an object by property value in an array of JavaScript objects](http://stackoverflow.com/q/7364150/3853934) – Michał Perłakowski May 15 '16 at 12:46
  • 1
    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 – Mark Seagoe May 12 '19 at 05:07

17 Answers17

1781

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)
Alireza
  • 100,211
  • 27
  • 269
  • 172
elclanrs
  • 92,861
  • 21
  • 134
  • 171
  • 174
    This will return an array – nickf Dec 20 '12 at 02:03
  • 45
    @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. – elclanrs Dec 20 '12 at 02:05
  • 2
    Yeah, I guess it depends on what's needed. If it is just one item, I think `filter` isn't a great option, since it will firstly create a new unneeded object, and secondly it will continue through the entire array even when the object is found. – nickf Dec 20 '12 at 07:36
  • 7
    It's worth mentioning that `filter` is only supported in modern browsers (i.e. IE9 and above) as it's part of ES5. So if you want to support older browsers you might want to fall back on one of the other methods suggested. – simonrohrbach Dec 06 '13 at 10:19
  • 34
    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]; – Rap Oct 27 '15 at 14:18
  • 36
    The question is "get JavaScript *object*", not "array of objects". – Michał Perłakowski Feb 14 '16 at 21:02
  • 29
    @Gothdo is right. To get object we can use Array.find: var result = jsObjects.find(function( obj ) { return obj.b === 6; }); – kolodi Apr 27 '16 at 09:49
  • if I change something in a result object, will it be also changed in the jsObjects array? – Cold_Class Apr 17 '17 at 14:05
  • Using the exact number 6 isn't useful for me. How do you pass in a variable? – user3925803 Jun 13 '17 at 12:37
  • @user3925803 - if you have `var x = 6;` above `var result`, just replace the hard-coded `6` in the function with your variable (`x`). – ps2goat Jun 22 '17 at 20:03
  • also there is a tiny utility for this called [super-array](https://www.npmjs.com/package/super-array) – patotoma Sep 24 '17 at 17:47
  • We should actually be using find: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find It functions the same as filter but returns the first matching object, not an array. – VoA Mar 29 '18 at 04:08
  • @VoA `find()` is an option, but it's not a "should" thing as every development house is different and not all are standardized on ES6 (especially in big companies where change is slow). If someone wants to return the first found object using `filter()`, then they just have to tack `[0]` to the end. – thdoan Apr 22 '18 at 20:47
  • @thdoan Yeah sure I hear you. – VoA Apr 23 '18 at 02:42
  • @elclanrs is the element of result shallow copy of elements of jsObjects or deep copy? – TSR Sep 22 '18 at 21:42
  • How could find the value in both a and b values? – reegan29 Dec 06 '18 at 13:23
  • Also... when using a var... use == instead of === – James Ikubi Jun 24 '20 at 07:40
  • this answer broke my form. return val should be json; filter returns an array – J.E.C. Nov 19 '20 at 13:40
  • 1
    @J.E.C. - technically, *you* broke your form when you thought this answer was what you needed. The answer is solid for at least 1500 other people. – ashleedawg Sep 04 '21 at 13:21
478
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.

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
  • 7
    Note that this is not supported in IE – 29er Sep 21 '16 at 23:03
  • 57
    @29er Yes, I wrote that "methods like `find()` and arrow functions are not supported by all browsers". – Michał Perłakowski Sep 22 '16 at 13:43
  • 4
    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 – ahaurat Jul 03 '17 at 19:04
  • This is not exactly equivalent to @elclanrs's answer using `filter()`: it returns only the first match. – thdoan Apr 22 '18 at 20:34
  • 6
    @thdoan The OP asked for "the object", not "an array of matching objects". elclanrs's answer is wrong. – Michał Perłakowski Apr 22 '18 at 21:29
  • This example uses ECMAScript 6 arrow function. In case of errors when using arrow functions, there are other ways out. See (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find) and (https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/) – ColinWa Oct 01 '18 at 09:28
  • 1
    Upvoted because it's not supported by IE. It's time to move on and I'm using it for that very reason. – RayLoveless Jan 13 '22 at 20:42
196

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;
      }
    }
  }
}
Aryan
  • 3,338
  • 4
  • 18
  • 43
RobG
  • 142,382
  • 31
  • 172
  • 209
75

Ways to achieve the requirement :

  1. 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);
  1. 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]);
  1. 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]);
  }
}
Debug Diva
  • 26,058
  • 13
  • 70
  • 123
33

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}]
Alireza
  • 100,211
  • 27
  • 269
  • 172
  • 2
    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]; – user3658510 Apr 24 '18 at 20:57
30

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 }
asrulsibaoel
  • 500
  • 1
  • 7
  • 14
23

Using underscore.js:

var foundObject = _.findWhere(jsObjects, {b: 6});
maia
  • 3,910
  • 4
  • 27
  • 34
21

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
Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
Amir
  • 720
  • 8
  • 18
19

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);
Sam Dushay
  • 301
  • 2
  • 5
18

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;
});
nickf
  • 537,072
  • 198
  • 649
  • 721
  • 3
    [`some`](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.17) just returns true or false, it doesn't return the matching object. – RobG Dec 20 '12 at 02:38
  • 6
    @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. – nickf Dec 20 '12 at 07:30
  • 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. – Michał Perłakowski Feb 14 '16 at 20:59
  • @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. – nickf Feb 16 '16 at 09:58
14

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}
Shobhit Sharma
  • 483
  • 4
  • 11
11

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().

Simple-Solution
  • 4,209
  • 12
  • 47
  • 66
8

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];
        }
    }
}
Andrew
  • 18,680
  • 13
  • 103
  • 118
6
var result = jsObjects.filter(x=> x.b === 6);

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

Died
  • 141
  • 2
  • 4
3

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%
}
<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>
kolodi
  • 1,002
  • 9
  • 16
2

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 }));
Serjuice
  • 569
  • 4
  • 16
-31
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;

Misa Lazovic
  • 2,805
  • 10
  • 32
  • 38