1760

I've got an array:

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}, etc.]

I'm unable to change the structure of the array. I'm being passed an id of 45, and I want to get 'bar' for that object in the array.

How do I do this in JavaScript or using jQuery?

Liam
  • 22,818
  • 25
  • 93
  • 157
thugsb
  • 19,348
  • 6
  • 28
  • 43

35 Answers35

1584

Use the find() method:

myArray.find(x => x.id === '45').foo;

From MDN:

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


If you want to find its index instead, use findIndex():

myArray.findIndex(x => x.id === '45');

From MDN:

The findIndex() method returns the index of the first element in the array that satisfies the provided testing function. Otherwise -1 is returned.


If you want to get an array of matching elements, use the filter() method instead:

myArray.filter(x => x.id === '45');

This will return an array of objects. If you want to get an array of foo properties, you can do this with the map() method:

myArray.filter(x => x.id === '45').map(x => x.foo);

Side note: methods like find() or filter(), 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 (with the polyfill).

meager
  • 209,754
  • 38
  • 307
  • 315
Michał Perłakowski
  • 70,955
  • 24
  • 137
  • 155
  • 4
    For multiple testing conditions would it therefore be something like: myArray.find(x => x.id === '45' && x.color == 'red').foo – Apqu Oct 20 '16 at 10:33
  • 3
    For me, best answer so far. Doesn't need jQuery neither creating new auxiliar arrays. – Canta Nov 13 '17 at 17:38
  • myArray.find(x => x.id === '45') it does not work on mac PC – Govinda Rajbhar May 30 '18 at 13:13
  • @T.J.Crowder I don't think that it's a good idea to copy-paste polyfills from MDN into your code; instead, you should use npm packages with polyfills. And Babel does include polyfills for ES2015+ features, in the [babel-polyfill](https://babeljs.io/docs/usage/polyfill/) package. – Michał Perłakowski Jun 04 '18 at 17:50
  • @MichałPerłakowski - I did say *"(Babel can also include polyfills for some things)"* And agreed, polyfilling has moved on since copy-and-paste from MDN. :-) – T.J. Crowder Jun 04 '18 at 18:23
  • 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:22
  • filter actually has support back to IE9! – Leland Mar 14 '19 at 16:54
  • 3
    myArray.find(x => x.id === '45').foo; throws an exception if there is no object with an id of '45'. – Frazer Kirkman Apr 10 '19 at 17:34
  • Nice explanation, I wasted more than a week trying to find out the solution how to read some elements from array (based on index) written on similar way. Thanks man. – Isma Nov 23 '20 at 14:33
  • TIL .findIndex() will not work (always returns -1 even when there's a matching obj) if using a statement block, e.g.: myArray.findIndex((x) => { x.id === '45' }); ... go figure – Whiskey T. Dec 16 '20 at 15:44
  • 1
    Can I add multiple condition inside the `find` method? – Si8 Dec 22 '20 at 02:51
1476

As you are already using jQuery, you can use the grep function which is intended for searching an array:

var result = $.grep(myArray, function(e){ return e.id == id; });

The result is an array with the items found. If you know that the object is always there and that it only occurs once, you can just use result[0].foo to get the value. Otherwise you should check the length of the resulting array. Example:

if (result.length === 0) {
  // no result found
} else if (result.length === 1) {
  // property found, access the foo property using result[0].foo
} else {
  // multiple items found
}
CodeJunkie
  • 196
  • 1
  • 14
Guffa
  • 640,220
  • 96
  • 678
  • 956
  • 127
    It'd be safer to use `===` instead of `==`, to avoid weird issues with JavaScript's `==` operator. – Vicky Chijwani Dec 11 '12 at 12:03
  • 11
    @VickyChijwani: Are there any issues when comparing a string to a string? – Guffa Dec 11 '12 at 12:17
  • 39
    Well, if you're _absolutely_ sure that both `e.id` and `id` will be strings, I suppose it's ok to use `==`. But if you're not sure, you might face problems (since `'' == 0` is `true` but `'' === 0` is `false`). Not to mention `===` seems to be faster (http://stackoverflow.com/questions/359494/javascript-vs-does-it-matter-which-equal-operator-i-use#comment14900957_359494). – Vicky Chijwani Dec 11 '12 at 13:19
  • 103
    Basically I always use `===` because it works _exactly_ like `==` in other programming languages. I consider `==` to be non-existent in JavaScript. – Vicky Chijwani Dec 11 '12 at 13:27
  • 6
    @de. Many answers here provide the intended behavior when looking up unique values; you can essentially recognize them by the fact that they return or break from their loop early (or instruct a lower-level construct to stop iterating). See JaredPar's answer for a canonical example, and Aaronius's comment on that answer for the same insight. In general, people differentiate between "filter" and "find" functions in this way, but terminology varies. Though more efficient, this is still a linear search, so if you want to use a hash table, see Aaron Digulla's answer (beware of impl. details). – tne Mar 12 '14 at 11:41
  • @tne: Note that there is nothing in the question that specifically says that the id is unique, and that my answer doesn't do that assumption. – Guffa Mar 12 '14 at 13:02
  • 2
    @Guffa: Indeed, your answer is absolutely correct with regard to the question as it is stated -- I just felt like pointing it out since it'll likely concern many readers who might otherwise miss an opportunity to do the right thing when they can (when the search property contains unique values). – tne Mar 12 '14 at 13:23
  • once you have `result`, just do `myArray.pop(result)` – stevenspiel Oct 23 '14 at 14:25
  • @mr.musicman: What are you trying to accomplish with that? The `pop` method doesn't take a parameter, so it will just remove the last item from the array and return it. – Guffa Oct 23 '14 at 17:15
  • @MatíasFidemraizer: The `filter` method is not supported in older browsers like IE 8, so using a library like jQuery is still a good option if you need it to work for as many as possible. – Guffa Jan 07 '15 at 09:03
  • @Guffa Who cares about IE8 now. It's an edge case. Since you're answer is the selected as right one, a lot of novice JS devs won't know about `filter` because of your answer! You've a lot of responsibility :D – Matías Fidemraizer Jan 07 '15 at 09:05
  • 3
    @MatíasFidemraizer: This answer doesn't try to list all possible solutions, it only shows the simplest and most compatible solution in the situation specified in the question. IE 8 is still too common for advocating a solution that doesn't support it, when there is a solution that is as simple and does support it. – Guffa Jan 07 '15 at 12:08
  • I've created a tiny utility just for this where you can access with O(1) called [super-array](https://www.npmjs.com/package/super-array) – patotoma Sep 24 '17 at 17:41
367

Another solution is to create a lookup object:

var lookup = {};
for (var i = 0, len = array.length; i < len; i++) {
    lookup[array[i].id] = array[i];
}

... now you can use lookup[id]...

This is especially interesting if you need to do many lookups.

This won't need much more memory since the IDs and objects will be shared.

Aaron Digulla
  • 297,790
  • 101
  • 558
  • 777
  • 6
    Exactly what I was looking for. Funny how I was trying to over-complicate it by trying to loop through each time, removing each item from the list as I found it when I only needed to mutate the received data from CouchDB and get it into a format that is useful for my needs. +1 sir! – slickplaid Feb 07 '13 at 17:18
  • 5
    this is smart. I can't imagine how others were convinced by looking all over the array for each use. – Aladdin Mhemed Feb 20 '13 at 05:52
  • 4
    As long as you don't rely on the order of properties: http://stackoverflow.com/questions/4886314/chrome-and-probably-opera-sort-object-properties-automatically – Marle1 Nov 05 '14 at 16:28
  • Is using a break; in the loop a good option / improvement if you know there is only one object to find ? – irJvV Sep 24 '15 at 13:09
  • 7
    @irJvV: No, that doesn't make sense at all. The code above is useful if you need to do many lookups. If you look just once, then creating a `lookup` object is a waste of time. – Aaron Digulla Sep 24 '15 at 13:40
  • @AaronDigulla thanks you are right. The lookup replaces the array because the objects from the array are stored under their id in var lookup. To save memory i deleted the original array with array = [ ]; – irJvV Sep 24 '15 at 14:00
  • I love that approach. I was looking for away avoiding the constant O(N) for every lookup. I can live peacefully with the O(N) for updates since they don't occur as often as reads are happening :) – kfirba Nov 02 '15 at 16:36
  • I created a array function based on @AaronDigulla's answer. It converts the array into an object, using a given key ( Usage: myArray.toObj('id'); ) --> Array.prototype.toObj=function(r){var t,o,n=this,e={};for(t=0,o=n.length;o>t;t++)e[n[t][r]]=n[t];return e;}; – pensan Nov 13 '15 at 15:33
  • This is great. As a side note, is there any significant benefit to setting the array len in the first statement of the for loop? I usually write it like this: (var x = 0; x < array.length; x++). Hadn't seen that before and curious. – jbd Mar 07 '16 at 19:04
  • @jbd I have to admit that I probably copied the code from somewhere. When JavaScript was still interpreted, it was probably a small speed boost since local variables are faster than indirect references. Also, it should catch a couple of problems when you change the size of the array in the loop ... which no one ever does ;-) – Aaron Digulla Mar 17 '16 at 16:01
  • Just to have this noted here: With this approach you convert the object to a hashmap so you have O(n) for the first lookup (since you need to convert first) and O(1) for each following one. – Aides Jun 28 '16 at 15:16
  • Thanks for your good answer, Is this a faster way? or is this way fast enough – Mohammad Kermani Aug 17 '16 at 08:16
  • This is the best solution as subsequent search of a specific id will require only O(1) – Simoyw Feb 09 '17 at 13:38
198

ECMAScript 2015 (JavaScript ES6) provides the find() method on arrays:

var myArray = [
 {id:1, name:"bob"},
 {id:2, name:"dan"},
 {id:3, name:"barb"},
]

// grab the Array item which matchs the id "2"
var item = myArray.find(item => item.id === 2);

// print
console.log(item.name);

It works without external libraries. But if you want older browser support you might want to include this polyfill.

Henke
  • 1,466
  • 2
  • 9
  • 22
Rúnar Berg
  • 3,247
  • 1
  • 14
  • 35
  • 1
    Probably cause it still seems very experimental and not many browsers support it, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find – lejonl Feb 19 '14 at 22:57
  • 2
    This can be simplified to `myArray.find(d=>d.id===45).foo;`. – Shaggy Mar 06 '17 at 11:29
  • 2
    @Shaggy or even `myArray.find(({ id }) => id === 45).foo`. But this is an old answer that was written before ES2015 syntax was as well supported as now. @Gothdo’s [answer](http://stackoverflow.com/a/35398031/2444959) is currently the most up to date in the thread. – Rúnar Berg Mar 06 '17 at 19:49
  • 1
    @Shaggy if the .find() returns undefined, then your optimization throws an error. So this solution is can be used only in cases where a match is guaranteed. – Herbert Peters Apr 03 '18 at 00:57
  • 1
    @HerbertPeters If you want to be sure you can alway null-check, which will be really easy with [optional chaining](https://github.com/tc39/proposal-optional-chaining): `myArray.find(d => d.id === 45)?.foo`. – Rúnar Berg Apr 03 '18 at 20:14
  • This solution is for ES6 and it doesn't compatible with IE browser. – Milad Rashidi Aug 14 '18 at 06:16
  • 1
    @MiladRashidi Like the answer states there is a [polyfill](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find#Polyfill) if you want older browser support. Likewise it is easy to rewrite using the older syntax. – Rúnar Berg Aug 16 '18 at 20:25
142

Underscore.js has a nice method for that:

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'},etc.]
obj = _.find(myArray, function(obj) { return obj.id == '45' })
GijsjanB
  • 9,396
  • 4
  • 21
  • 26
  • 42
    For the record, Lo-Dash (which is often demonstrably more performant than Underscore) has a similar method. Docs here: http://lodash.com/docs#find – user456584 Jan 16 '14 at 23:22
  • If you are expecting only one object, then using findWhere would be more efficient as after finding one result, the search would not go any further. – Foreever Oct 20 '15 at 04:00
  • @Foreever From the docs of _.find: "The function returns as soon as it finds an acceptable element, and doesn't traverse the entire list." – GijsjanB Oct 20 '15 at 09:06
133

I think the easiest way would be the following, but it won't work on Internet Explorer 8 (or earlier):

var result = myArray.filter(function(v) {
    return v.id === '45'; // Filter out the appropriate one
})[0].foo; // Get result and access the foo property
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
pimvdb
  • 141,012
  • 68
  • 291
  • 345
  • I'm curious, is there any performance advantage here compared to the usual `for`? – Igor Zinov'yev Sep 09 '11 at 15:47
  • @Igor Zinov'yev: Yes, there certainly are performance impacts with those ES5 array tools. A separate function is executed for each element, so it won't be really fast compared to a direct `for` loop. – pimvdb Sep 09 '11 at 15:48
  • So you're saying that it would be slower? Also, it will always scan the whole array, as far as I can see, whereas the `for` loop will terminate on the first match. – Igor Zinov'yev Sep 09 '11 at 15:50
  • If you need support for IE8, just drop this in: http://stackoverflow.com/questions/7153470/why-wont-filter-work-in-interent-explorer-8 – Adam Grant Jul 17 '13 at 21:12
  • This code will throw an error if there's no element with that `id` – Stan Feb 23 '17 at 14:57
76

Try the following

function findById(source, id) {
  for (var i = 0; i < source.length; i++) {
    if (source[i].id === id) {
      return source[i];
    }
  }
  throw "Couldn't find object with id: " + id;
}
JaredPar
  • 673,544
  • 139
  • 1,186
  • 1,421
  • 17
    This wasn't worthy of its own answer, but in modern browsers this solution can be written as: http://jsfiddle.net/rwaldron/j3vST/ – Rick Sep 09 '11 at 15:50
  • 12
    If you're going for efficiency, note that this example is likely faster than using filter() (see Rick's example) since this one returns once it finds the first matching item whereas filter() continues running through the full array even after finding a match. This one also doesn't have the cost of creating an additional array or calling a function for each item. – Aaronius Aug 02 '13 at 19:28
  • 3
    @Rick, the most interesting thing about that answer is apparently you can add the firebug console to the output window in jsFiddle. This is so much better than logging and telling someone else to open the console to see the output. Awesome! – KyleMit Aug 29 '14 at 23:48
  • 1
    Since noone has mentioned it so far, I wanted to add that AngularJS also has a [filter](https://docs.angularjs.org/api/ng/filter/filter) method. – Eno Feb 04 '15 at 22:37
  • @JaredPar https://stackoverflow.com/questions/44550439/javascript-search-array-of-nested-objects-and-return-parent-if-value-is-found – Valay Jun 14 '17 at 21:27
45
myArray.filter(function(a){ return a.id == some_id_you_want })[0]
Danilo Colasso
  • 2,214
  • 15
  • 11
  • Ployfill for older browsers: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Polyfill – Justin Aug 21 '15 at 18:00
  • @Danilo how can I search within nested object ? https://stackoverflow.com/questions/44550439/javascript-search-array-of-nested-objects-and-return-parent-if-value-is-found – Valay Jun 14 '17 at 21:25
32

A generic and more flexible version of the findById function above:

// array = [{key:value},{key:value}]
function objectFindByKey(array, key, value) {
    for (var i = 0; i < array.length; i++) {
        if (array[i][key] === value) {
            return array[i];
        }
    }
    return null;
}

var array = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
var result_obj = objectFindByKey(array, 'id', '45');
will Farrell
  • 1,549
  • 1
  • 15
  • 19
18

Performance

Today 2020.06.20 I perform test on MacOs High Sierra on Chrome 81.0, Firefox 77.0 and Safari 13.1 for chosen solutions.

Conclusions for solutions which use precalculations

Solutions with precalculations (K,L) are (much much) faster than other solutions and will not be compared with them - probably they are use some special build-in browser optimisations

  • surprisingly on Chrome and Safari solution based on Map (K) are much faster than solution based on object {} (L)
  • surprisingly on Safari for small arrays solution based on object {} (L) is slower than traditional for (E)
  • surprisingly on Firefox for small arrays solution based on Map (K) is slower than traditional for (E)

Conclusions when searched objects ALWAYS exists

  • solution which use traditional for (E) is fastest for small arrays and fast for big arrays
  • solution using cache (J) is fastest for big arrays - surprisingly for small arrays is medium fast
  • solutions based on find (A) and findIndex (B) are fast for small arras and medium fast on big arrays
  • solution based on $.map (H) is slowest on small arrays
  • solution based on reduce (D) is slowest on big arrays

enter image description here

Conclusions when searched objects NEVER exists

  • solution based on traditional for (E) is fastest on small and big arrays (except Chrome-small arrays where it is second fast)
  • solution based on reduce (D) is slowest on big arrays
  • solution which use cache (J) is medium fast but can be speed up if we save in cache also keys which have null values (which was not done here because we want to avoid unlimited memory consumption in cache in case when many not existing keys will be searched)

enter image description here

Details

For solutions

  • without precalculations: A B C D E F G H I J (the J solution use 'inner' cache and it speed depend on how often searched elements will repeat)
  • with precalculations K L

I perform four tests. In tests I want to find 5 objects in 10 loop iterations (the objects ID not change during iterations) - so I call tested method 50 times but only first 5 times have unique id values:

  • small array (10 elements) and searched object ALWAYS exists - you can perform it HERE
  • big array (10k elements) and searched object ALWAYS exist - you can perform it HERE
  • small array (10 elements) and searched object NEVER exists - you can perform it HERE
  • big array (10k elements) and searched object NEVER exists - you can perform it HERE

Tested codes are presented below

function A(arr, id) {
  return arr.find(o=> o.id==id);
}

function B(arr, id) {
  let idx= arr.findIndex(o=> o.id==id);
  return arr[idx];
}

function C(arr, id) {
  return arr.filter(o=> o.id==id)[0];
}

function D(arr, id) {
  return arr.reduce((a, b) => (a.id==id && a) || (b.id == id && b));
}

function E(arr, id) {
  for (var i = 0; i < arr.length; i++) if (arr[i].id==id) return arr[i];
  return null;
}

function F(arr, id) {
  var retObj ={};
  $.each(arr, (index, obj) => {
    if (obj.id == id) { 
      retObj = obj;
      return false;
    }
  });
  return retObj;
}

function G(arr, id) {
  return $.grep(arr, e=> e.id == id )[0];
}

function H(arr, id) {
  return $.map(myArray, function(val) {
    return val.id == id ? val : null;
  })[0];
}

function I(arr, id) {
  return _.find(arr, o => o.id==id);
}

let J = (()=>{
  let cache = new Map();
  return function J(arr,id,el=null) { 
    return cache.get(id) || (el=arr.find(o=> o.id==id), cache.set(id,el), el);
  }
})();

function K(arr, id) {
  return mapK.get(id)
}

function L(arr, id) {
  return mapL[id];
}



// -------------
// TEST
// -------------

console.log('Find id=5');

myArray = [...Array(10)].map((x,i)=> ({'id':`${i}`, 'foo':`bar_${i}`}));
const mapK = new Map( myArray.map(el => [el.id, el]) );
const mapL = {}; myArray.forEach(el => mapL[el.id]=el);



[A,B,C,D,E,F,G,H,I,J,K,L].forEach(f=> console.log(`${f.name}: ${JSON.stringify(f(myArray, '5'))}`));

console.log('Whole array',JSON.stringify(myArray));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

This snippet only presents tested codes

Example tests results for Chrome for small array where searched objects always exists

enter image description here

Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
15

You can get this easily using the map() function:

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];

var found = $.map(myArray, function(val) {
    return val.id == 45 ? val.foo : null;
});

//found[0] == "bar";

Working example: http://jsfiddle.net/hunter/Pxaua/

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
hunter
  • 58,834
  • 17
  • 108
  • 112
  • 1
    I forgot about the fact that jQuery's `map` automatically removes `null` elements. It sounds misleading to me and to the common concept of `map`, as the result is not of the same length of the original collection. – MaxArt Sep 05 '14 at 14:30
14

You can use filters,

  function getById(id, myArray) {
    return myArray.filter(function(obj) {
      if(obj.id == id) {
        return obj 
      }
    })[0]
  }

get_my_obj = getById(73, myArray);
Joe Lewis
  • 1,741
  • 2
  • 15
  • 13
  • 1
    @TobiasBeuving - The one using Array.find() is plain JS too and should stop on the first find so will be more efficient. – Adrian Lynch Oct 07 '15 at 20:19
14

Using native Array.reduce

var array = [ {'id':'73' ,'foo':'bar'} , {'id':'45' ,'foo':'bar'} , ];
var id = 73;
var found = array.reduce(function(a, b){
    return (a.id==id && a) || (b.id == id && b)
});

returns the object element if found, otherwise false

Community
  • 1
  • 1
laggingreflex
  • 26,275
  • 28
  • 123
  • 172
13

While there are many correct answers here, many of them do not address the fact that this is an unnecessarily expensive operation if done more than once. In an extreme case this could be the cause of real performance problems.

In the real world, if you are processing a lot of items and performance is a concern it's much faster to initially build a lookup:

var items = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];

var lookup = items.reduce((o,i)=>o[i.id]=o,{});

you can then get at items in fixed time like this :

var bar = o[id];

You might also consider using a Map instead of an object as the lookup: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map

Tom
  • 7,474
  • 7
  • 40
  • 56
11

If you do this multiple times, you may set up a Map (ES6):

const map = new Map( myArray.map(el => [el.id, el]) );

Then you can simply do:

map.get(27).foo
Jonas Wilms
  • 106,571
  • 13
  • 98
  • 120
7

Recently, I have to face the same thing in which I need to search the string from a huge array.

After some search I found It'll be easy to handle with simple code:

Code:

var items = mydata.filter(function(item){
    return item.word.toLowerCase().startsWith( 'gk );
})

See https://jsfiddle.net/maheshwaghmare/cfx3p40v/4/

Serach from 20k strings

maheshwaghmare
  • 1,462
  • 15
  • 22
6

Here's how I'd go about it in pure JavaScript, in the most minimal manner I can think of that works in ECMAScript 3 or later. It returns as soon as a match is found.

var getKeyValueById = function(array, key, id) {
    var testArray = array.slice(), test;
    while(test = testArray.pop()) {
        if (test.id === id) {
            return test[key];
        }
    }
    // return undefined if no matching id is found in array
    return;
}

var myArray = [{'id':'73', 'foo':'bar'}, {'id':'45', 'foo':'bar'}]
var result = getKeyValueById(myArray, 'foo', '45');

// result is 'bar', obtained from object with id of '45'
Dan W
  • 744
  • 5
  • 8
6

More generic and short

function findFromArray(array,key,value) {
        return array.filter(function (element) {
            return element[key] == value;
        }).shift();
}

in your case Ex. var element = findFromArray(myArray,'id',45) that will give you the whole element.

5

You may try out Sugarjs from http://sugarjs.com/.

It has a very sweet method on Arrays, .find. So you can find an element like this:

array.find( {id: 75} );

You may also pass an object with more properties to it to add another "where-clause".

Note that Sugarjs extends native objects, and some people consider this very evil...

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
deepflame
  • 858
  • 1
  • 7
  • 17
  • 2
    Well, it _is_ evil, since it may happen that new EcmaScript versions may introduce new methods with the same name. And guess what, this is [exactly what happened with `find`](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.find). My suggestion is that if you want to extend native prototypes, always use more specific names, leaving the simplest ones to future standard developments. – MaxArt Sep 05 '14 at 14:21
  • this comment is nearly 2 years old and today I would rather use lodash anyways. However if you want you can read about this topic on the sugarjs website. They take a good stand to your opinion: http://sugarjs.com/native – deepflame Sep 22 '14 at 12:19
  • 1
    The op did specifically ask for a javascript or jquery solution – Tobias Beuving Feb 22 '15 at 14:41
5

As long as the browser supports ECMA-262, 5th edition (December 2009), this should work, almost one-liner:

var bFound = myArray.some(function (obj) {
    return obj.id === 45;
});
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
aggaton
  • 2,326
  • 2
  • 20
  • 29
  • 2
    Almost. `bFound` is just a boolean that is `true` iff an element satisfies the required condition. – MaxArt Sep 02 '14 at 12:29
5

As others have pointed out, .find() is the way to go when looking for one object within your array. However, if your object cannot be found using this method, your program will crash:

const myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
const res = myArray.find(x => x.id === '100').foo; // Uh oh!
/*
Error:
"Uncaught TypeError: Cannot read property 'foo' of undefined"
*/

This can be fixed by checking whether the result of .find() is defined before using using .foo on it. Modern JS allows us to do this easily with optional chaining, returning undefined if the object cannot be found, rather than crashing your code:

const myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
const res = myArray.find(x => x.id === '100')?.foo; // No error!
console.log(res); // undefined when the object cannot be found
Nick Parsons
  • 31,322
  • 6
  • 25
  • 44
5

Iterate over any item in the array. For every item you visit, check that item's id. If it's a match, return it.

If you just want teh codez:

function getId(array, id) {
    for (var i = 0, len = array.length; i < len; i++) {
        if (array[i].id === id) {
            return array[i];
        }
    }
    return null; // Nothing found
}

And the same thing using ECMAScript 5's Array methods:

function getId(array, id) {
    var obj = array.filter(function (val) {
        return val.id === id;
    });

    // Filter returns an array, and we just want the matching item.
    return obj[0];
}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Zirak
  • 35,198
  • 12
  • 75
  • 89
4

Building on the accepted answer:

jQuery:

var foo = $.grep(myArray, function(e){ return e.id === foo_id})
myArray.pop(foo)

Or CoffeeScript:

foo = $.grep myArray, (e) -> e.id == foo_id
myArray.pop foo
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
stevenspiel
  • 4,740
  • 10
  • 51
  • 82
4

Use Array.prototype.filter() function.

DEMO: https://jsfiddle.net/sumitridhal/r0cz0w5o/4/

JSON

var jsonObj =[
 {
  "name": "Me",
  "info": {
   "age": "15",
   "favColor": "Green",
   "pets": true
  }
 },
 {
  "name": "Alex",
  "info": {
   "age": "16",
   "favColor": "orange",
   "pets": false
  }
 },
{
  "name": "Kyle",
  "info": {
   "age": "15",
   "favColor": "Blue",
   "pets": false
  }
 }
];

FILTER

var getPerson = function(name){
    return jsonObj.filter(function(obj) {
      return obj.name === name;
    });
}
Sumit Ridhal
  • 1,211
  • 3
  • 9
  • 28
  • how can I search within nested object ? Like pets= false should return two objects. – Valay Jun 14 '17 at 21:22
  • use `.filter` method on `obj.info` in nested loop. ``var getPerson = function(name){ return jsonObj.filter(function(obj) { return obj.info.filter(function(info) { return pets === false; }); }); }`` – Sumit Ridhal Jun 17 '17 at 18:07
  • you could use es6 style too imo... const filterData = jsonObj.filter(obj => obj.name === 'Alex') – DagicCross Jun 08 '18 at 02:10
4

We can use Jquery methods $.each()/$.grep()

var data= [];
$.each(array,function(i){if(n !== 5 && i > 4){data.push(item)}}

or

var data = $.grep(array, function( n, i ) {
  return ( n !== 5 && i > 4 );
});

use ES6 syntax:

Array.find, Array.filter, Array.forEach, Array.map

Or use Lodash https://lodash.com/docs/4.17.10#filter, Underscore https://underscorejs.org/#filter

Samuel Liew
  • 68,352
  • 105
  • 140
  • 225
TLbiz
  • 399
  • 5
  • 7
3

You can do this even in pure JavaScript by using the in built "filter" function for arrays:

Array.prototype.filterObjects = function(key, value) {
    return this.filter(function(x) { return x[key] === value; })
}

So now simply pass "id" in place of key and "45" in place of value, and you will get the full object matching an id of 45. So that would be,

myArr.filterObjects("id", "45");
kaizer1v
  • 868
  • 8
  • 20
2

This solution may helpful as well:

Array.prototype.grep = function (key, value) {
    var that = this, ret = [];
    this.forEach(function (elem, index) {
        if (elem[key] === value) {
            ret.push(that[index]);
        }
    });
    return ret.length < 2 ? ret[0] : ret;
};
var bar = myArray.grep("id","45");

I made it just like $.grep and if one object is find out, function will return the object, rather than an array.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
soytian
  • 178
  • 3
2

I really liked the answer provided by Aaron Digulla but needed to keep my array of objects so I could iterate through it later. So I modified it to

 var indexer = {};
 for (var i = 0; i < array.length; i++) {
     indexer[array[i].id] = parseInt(i);
 }
 
 //Then you can access object properties in your array using 
 array[indexer[id]].property
quincyaft
  • 45
  • 3
  • Used same solution as fastest for finding items in array. But parseInt is redundant here. – aleha Sep 25 '16 at 17:30
1

Use:

var retObj ={};
$.each(ArrayOfObjects, function (index, obj) {

        if (obj.id === '5') { // id.toString() if it is int

            retObj = obj;
            return false;
        }
    });
return retObj;

It should return an object by id.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
volumexxx
  • 43
  • 2
  • you could shorten your code by using return obj.id === 5 ? obj : false; I use $.each a lot for iterating over arrays. – marcel Apr 08 '14 at 06:53
  • @marcel: That won't work. As returning false will end the loop, it would only find the object if it was the first item in the array. – Guffa Apr 05 '15 at 19:43
1

Dynamic cached find

In this solution, when we search for some object, we save it in cache. This is middle point between "always search solutions" and "create hash-map for each object in precalculations".

let cachedFind = (()=>{
  let cache = new Map();
  return (arr,id,el=null) => 
    cache.get(id) || (el=arr.find(o=> o.id==id), cache.set(id,el), el);
})();


// ---------
// TEST
// ---------

let myArray = [...Array(100000)].map((x,i)=> ({'id':`${i}`, 'foo':`bar_${i}`}));

// example usage

console.log( cachedFind(myArray,'1234').foo );





// Benchmark

let bench = (id) => {
  console.time   ('time for '+id ); 
  console.log    ( cachedFind(myArray,id).foo );  // FIND
  console.timeEnd('time for '+id );
}

console.log('----- no cached -----');
bench(50000);
bench(79980);
bench(99990);
console.log('-----  cached   -----');
bench(79980); // cached
bench(99990); // cached
Community
  • 1
  • 1
Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
0

Starting from aggaton's answer, this is a function that actually returns the wanted element (or null if not found), given the array and a callback function that returns a truthy value for the "correct" element:

function findElement(array, callback) {
    var elem;
    return array.some(function(e) {
        if (callback(e)) {
            elem = e;
            return true;
        }
    }) ? elem : null;
});

Just remember that this doesn't natively work on IE8-, as it doesn't support some. A polyfill can be provided, alternatively there's always the classic for loop:

function findElement(array, callback) {
    for (var i = 0; i < array.length; i++)
        if (callback(array[i])) return array[i];
    return null;
});

It's actually faster and more compact. But if you don't want to reinvent the wheel, I suggest using an utility library like underscore or lodash.

Community
  • 1
  • 1
MaxArt
  • 20,295
  • 8
  • 70
  • 78
0

Shortest,

var theAnswerObj = _.findWhere(array, {id : 42});
Manu
  • 609
  • 7
  • 18
-1

Consider "axesOptions" to be array of objects with an object format being {:field_type => 2, :fields => [1,3,4]}

function getFieldOptions(axesOptions,choice){
  var fields=[]
  axesOptions.each(function(item){
    if(item.field_type == choice)
        fields= hashToArray(item.fields)
  });
  return fields;
}
ramya
  • 281
  • 1
  • 4
  • 12
-3

My way to find index of array:

index = myArray.map((i) => i.id).indexOf(value_of_id);
item = myArray[index];
Vu Truong
  • 869
  • 7
  • 9
-5

Use the filter method of jQuery:

 $(myArray).filter(function()
 {
     return this.id == desiredId;
 }).first();

That will return the first element with the specified Id.

It also has the benefit of a nice C# LINQ looking format.

Tejs
  • 38,896
  • 8
  • 64
  • 81
  • 4
    The `filter` method is intended for elements, not arrays. Use the `grep` method instead. – Guffa Sep 09 '11 at 15:56