48
var set = [{"color":"blue"},{"color":"green"},{"color":"red"},{"color":"green"}];

I'd like to be able to do something like a db call, set.find({"color":"green"}) and have it return an array full of objects that contain that property.

Domenic
  • 110,262
  • 41
  • 219
  • 271
fancy
  • 48,619
  • 62
  • 153
  • 231

5 Answers5

88

Using Array#filter, for this particular case the code would look like

var results = set.filter(function (entry) { return entry.color === "green"; });

Array#filter is not implemented in some older browsers, so see the linked article for a backward compatibility shim, or better yet get a full-fledged ES5 shim.

For the more general case, it's just a matter of extending this idea:

function findByMatchingProperties(set, properties) {
    return set.filter(function (entry) {
        return Object.keys(properties).every(function (key) {
            return entry[key] === properties[key];
        });
    });
}

var results = findByMatchingProperties(set, { color: "green" });

Again, I am using ECMAScript 5 methods Object.keys and Array#every, so use an ES5 shim. (The code is doable without an ES5 shim but uses manual loops and is much less fun to write and read.)

Domenic
  • 110,262
  • 41
  • 219
  • 271
  • 4
    Even weirder that you're including the jQuery tag then. – Domenic Jun 04 '11 at 15:28
  • what would this look like as a method? set.find({color:"green"}), basically looking to create faux db functionality. – fancy Jun 04 '11 at 15:49
  • @float, are you looking to add this method to all arrays, or just your custom objects, or...? If the former, what do you expect it to do for an array of integers? – Domenic Jun 04 '11 at 15:51
  • it could just be on a user object, so findUser() finds their object in the user array - doesn't need to be a general method. – fancy Jun 04 '11 at 16:16
  • Well you're welcome to post a followup question on how methods work in JavaScript, but just to get you started, `var users = { users: [], findUser: function (properties) { return findByMatchingProperties(this.users, properties); } };` – Domenic Jun 04 '11 at 16:19
  • I assume there aren't any problems using this in angular 2. Correct? – Adrian M. Dec 06 '16 at 15:48
3

I have used map function from jquery and I am getting selected index by passing searched key value so by using that index we will get required object from array.

var mydata = [{ name: "Ram", Id: 1 }, { name: "Shyam", Id: 2 }, { name: "Akhil", Id: 3 }];

searchKey = 2

var mydata = [{ name: "Ram", Id: 1 }, { name: "Shyam", Id: 2 }, { name: "Akhil", Id: 3 }];

searchKey = 2

var selectedData = mydata[mydata.map(function (item) { return item.Id; }).indexOf(searchKey)];

console.log(selectedData)
var selectedData = mydata[mydata.map(function (item) { return item.Id; }).indexOf(searchKey)];

console.log(selectedData)

output
{ name: "Shyam", Id: 2 }

Note: if you want to pass search key as object then
searchKey = { Id: 2 };

mydata[mydata.map(function (item) { return item.Id; }).indexOf(searchKey.Id)];

output
{ name: "Shyam", Id: 2 }
Derrick
  • 3,669
  • 5
  • 35
  • 50
  • jQuery's map function is exactly what I needed. Your code snippet is great and was the first one to suggest using map, so I up-voted yours. – Mark Jul 11 '18 at 20:14
3

Using arrow functions with an implied return and concise body:

const results = set.filter(entry => entry.color === "green");

Another example passing in a search variable:

const searchString = 'green'; 
const results = set.filter(entry => entry.color === `${searchString}`);

Read more about arrow functions on MDN

jhovanec
  • 796
  • 8
  • 8
1

Since you've included the jQuery tag, here's one way to do it using jQuery's map:

var results = $.map( set, function(e,i){
  if( e.color === 'green' ) return e; 
});

The documentation states that you need to return null to remove the element from the array, but apparently this is false, as shown by the jsFiddle in the comments; returning nothing (i.e. returning undefined) works just as well.

Domenic
  • 110,262
  • 41
  • 219
  • 271
Ken Redler
  • 23,863
  • 8
  • 57
  • 69
  • 1
    This will return `[undefined, { color: "green" }, undefined, undefined]`. – Domenic Jun 04 '11 at 15:28
  • 1
    @Ken Redler, I stand corrected. The documentation for `$.map` says it will only remove the element if you return `null`, but I guess it recognizes `undefined` as well. Still, I think usually you'd want to use `$.grep` for this. – Domenic Jun 04 '11 at 15:36
  • 1
    @Domenic, I do see that point about `null` in the documentation, but as far as I know it's always worked with the `undefined` of a function that has no return in some cases. I.e., omitting the return statement entirely has always resulted in an array with zero elements, if I recall correctly. – Ken Redler Jun 04 '11 at 15:46
  • @Ken Redler, yup, I believe you; I just think it sucks that their documentation doesn't mention this. – Domenic Jun 04 '11 at 15:50
  • 1
    @Domenic, I agree. I've submitted a documentation update suggestion to the jQuery team. – Ken Redler Jun 04 '11 at 16:11
  • You're better off using filter - map is functionally for changing a list of type A -> list of type B with the same number of elements. I'm not saying it doesn't work, but it's using the wrong tool for the job. – Dan G Apr 10 '17 at 12:24
0

I went with a different approach that I found to be a bit easier.

function isObjEqual(a, b) {
    const x = JSON.stringify(a);
    const y = JSON.stringify(b);
  
    return x === y;
  }

// Example 1
const set = [{"color":"blue"},{"color":"green"},{"color":"red"},{"color":"green"}];
const findObj1 = {"color":"green"};
const arr1 = set.filter((objInArr) => isObjEqual(objInArr, findObj1));
console.log(arr1) // [ { color: 'green' }, { color: 'green' } ]

  // Example 2
const list = [{
    "label": "Option 2",
    "value": "option2"
  },
  {
    "label": "Option 3",
    "value": "option3"
  },
  {
    "label": "Option 2",
    "value": "option2"
  }
];

const findObj2 = {
  "label": "Option 2",
  "value": "option2"
}

const newList = list.filter((objInArr) => isObjEqual(objInArr, findObj2));
console.log(newList) //[ { label: 'Option 2', value: 'option2' }, { label: 'Option 2', value: 'option2' } ]
Ballpin
  • 217
  • 2
  • 6