I have an array of objects:
Object = {
1 : { name : bob , dinner : pizza },
2 : { name : john , dinner : sushi },
3 : { name : larry, dinner : hummus
If you have an array such as
var people = [
{ "name": "bob", "dinner": "pizza" },
{ "name": "john", "dinner": "sushi" },
{ "name": "larry", "dinner": "hummus" }
];
You can use the filter method of an Array object:
people.filter(function (person) { return person.dinner == "sushi" });
// => [{ "name": "john", "dinner": "sushi" }]
In newer JavaScript implementations you can use a function expression:
people.filter(p => p.dinner == "sushi")
// => [{ "name": "john", "dinner": "sushi" }]
You can search for people who have "dinner": "sushi"
using a map
people.map(function (person) {
if (person.dinner == "sushi") {
return person
} else {
return null
}
}); // => [null, { "name": "john", "dinner": "sushi" }, null]
or a reduce
people.reduce(function (sushiPeople, person) {
if (person.dinner == "sushi") {
return sushiPeople.concat(person);
} else {
return sushiPeople
}
}, []); // => [{ "name": "john", "dinner": "sushi" }]
I'm sure you are able to generalize this to arbitrary keys and values!
You can use a simple for in loop:
for (prop in Obj){
if (Obj[prop]['dinner'] === 'sushi'){
// Do stuff with found object. E.g. put it into an array:
arrFoo.push(Obj[prop]);
}
}
The following fiddle example puts all objects that contain dinner:sushi
into an array:
https://jsfiddle.net/3asvkLn6/1/
I would try not to reinvent the wheel. We use object-scan for all our data processing needs. It's conceptually very simple, but allows for a lot of cool stuff. Here is how you would solve your specific question
const objectScan = require('object-scan');
const findDinner = (dinner, data) => objectScan(['*'], {
abort: true,
rtn: 'value',
filterFn: ({ value }) => value.dinner === dinner
})(data);
const data = {
1: { name: 'bob', dinner: 'pizza' },
2: { name: 'john', dinner: 'sushi' },
3: { name: 'larry', dinner: 'hummus' }
};
console.log(findDinner('sushi', data));
// => { name: 'john', dinner: 'sushi' }
There's already a lot of good answers here so why not one more, use a library like lodash or underscore :)
obj = {
1 : { name : 'bob' , dinner : 'pizza' },
2 : { name : 'john' , dinner : 'sushi' },
3 : { name : 'larry', dinner : 'hummus' }
}
_.where(obj, {dinner: 'pizza'})
>> [{"name":"bob","dinner":"pizza"}]
If you're going to be doing this search frequently, consider changing the format of your object so dinner actually is a key. This is kind of like assigning a primary clustered key in a database table. So, for example:
Obj = { 'pizza' : { 'name' : 'bob' }, 'sushi' : { 'name' : 'john' } }
You can now easily access it like this: Object['sushi']['name']
Or if the object really is this simple (just 'name' in the object), you could just change it to:
Obj = { 'pizza' : 'bob', 'sushi' : 'john' }
And then access it like: Object['sushi']
.
It's obviously not always possible or to your advantage to restructure your data object like this, but the point is, sometimes the best answer is to consider whether your data object is structured the best way. Creating a key like this can be faster and create cleaner code.
I had to search a nested sitemap structure for the first leaf item that machtes a given path. I came up with the following code just using .map()
.filter()
and .reduce
. Returns the last item found that matches the path /c
.
var sitemap = {
nodes: [
{
items: [{ path: "/a" }, { path: "/b" }]
},
{
items: [{ path: "/c" }, { path: "/d" }]
},
{
items: [{ path: "/c" }, { path: "/d" }]
}
]
};
const item = sitemap.nodes
.map(n => n.items.filter(i => i.path === "/c"))
.reduce((last, now) => last.concat(now))
.reduce((last, now) => now);