I'm trying to query an array of objects in JavaScript, and return objects that match a specific filter criteria.
I've managed - thanks to help from others - to filter a simple object, but now I need to apply the same thing to a more complex object.
// Simple object query:
var recipes = {
'soup': {'ingredients': ['carrot', 'pepper', 'tomato']},
'pie': {'ingredients': ['carrot', 'steak', 'potato']},
'stew': {'ingredients': ['steak', 'pepper', 'tomato']}
};
var shoppingList = ['carrot', 'steak', 'tomato', 'pepper']
var result = Object.entries(recipes)//1. get the key-value pairs
.filter(([key, {ingredients}]) => ingredients.every(t => shoppingList.includes(t))) //2. filter them
.map(([key]) => key) //3. get the keys only
console.log(result);
// More complex object:
var itemsTest = [
{
uid: 1,
items: [
{ item: { uid: "a" } },
{ item: { uid: "b" } },
{ item: { uid: "g" } }
]
},
{
uid: 2,
items: [
{ item: { uid: "b" } },
{ item: { uid: "q" } },
{ item: { uid: "f" } }
]
},
}
];
var filter = ["b", "q", "f"]
// Expect filter to return {uid: 2, items}
}
The recipes filter works great. But now I have a more complex array of objects, it seems the same approach isn't possible.
I want to filter itemsTest
according to the uid
of each item in the items
array. I'd be happy to use lodash, if it makes life easier.
I tried to flatten the array of objects using Object.entries()
, to no avail.
var flattened = objectMap(itemsList, function(value) {
return Object.entries(value);
});
var result = flattened.filter(([key, { uid }]) =>
uid.every(t => filter.includes(t))
)
I also tried a simplified approach filtering with one value using Array.filter.prototype()
, which doesn't work either:
var newArray = flattened.filter(function(el) {
return el.uid <= 2
});
console.log(newArray)
Any help understanding how to navigate an object like this would be great.
You can use Array.find()
(or Array.filter()
to iterate the array of objects. Now use Array.every()
, and for each item check if it's uid
is included in the filter
array.
const itemsTest = [{"uid":1,"items":[{"item":{"uid":"a"}},{"item":{"uid":"b"}},{"item":{"uid":"g"}}]},{"uid":2,"items":[{"item":{"uid":"b"}},{"item":{"uid":"q"}},{"item":{"uid":"f"}}]}];
const filter = ["b", "q", "f"];
const result = itemsTest.find(({ items }) => // use filter instead of find to get multiple items
items.every(o => filter.includes(o.item.uid))
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>