Reputation: 1852
Below is the sample array of objects.
I'm looking to filter this on basis of criteriaType
, id
& source
. If none of the input.source
match, the parent object should be filtered out. Also all the filter criteria are optional.
[{
"id": "9be6c6299cca48f597fe71bc99c37b2f",
"caption": "caption1",
"criteriaType": "type2",
"input": [
{
"id_1": "66be4486ffd3431eb60e6ea6326158fe",
"criteriaId": "9be6c6299cca48f597fe71bc99c37b2f",
"source": "type1",
},
{
"id_1": "1ecdf410b3314865be2b52ca9b4c8539",
"criteriaId": "9be6c6299cca48f597fe71bc99c37b2f",
"source": "type2",
}
]
},
{
"id": "b83b3f081a7b45e087183740b12faf3a",
"caption": "caption1",
"criteriaType": "type1",
"input": [
{
"id_1": "f46da7ffa859425e922bdbb701cfcf88",
"criteriaId": "b83b3f081a7b45e087183740b12faf3a",
"source": "type3",
},
{
"id_1": "abb87219db254d108a1e0f774f88dfb6",
"criteriaId": "b83b3f081a7b45e087183740b12faf3a",
"source": "type1",
}
]
},
{
"id": "fe5b071a2d8a4a9da61bbd81b9271e31",
"caption": "caption1",
"criteriaType": "type1",
"input": [
{
"id_1": "7ea1b85e4dbc44e8b37d1110b565a081",
"criteriaId": "fe5b071a2d8a4a9da61bbd81b9271e31",
"source": "type3",
},
{
"id_1": "c5f943b61f674265b8237bb560cbed03",
"criteriaId": "fe5b071a2d8a4a9da61bbd81b9271e31",
"source": "type3",
}
]
}]
I was able to achieve just filter by criteriaType
& id
. But I'm not able to filter by source
also to make sure that parent isn't returned if none of the input.source match.
var json = <<array of objects>> ;
const {objectId: id, ctype: criteriaType, inputSource: source } = param; // getting the the params
json = ctype ? json.filter(({criteriaType}) => criteriaType === ctype ): json;
json = (objectId ? json.filter(({id}) => id === objectId ): json)
.map (({id, caption, criteriaType, input }) => {
//some manipulation
return { //results after manipulation}
})
Help me out! Thanks in advance. I'm not sure if we could chain filters to achieve it.
looking for esLint compatible code
Upvotes: 2
Views: 4779
Reputation: 1156
Try this:
var obj = [{
"id": "9be6c6299cca48f597fe71bc99c37b2f",
"caption": "caption1",
"criteriaType": "type2",
"input": [
{
"id_1": "66be4486ffd3431eb60e6ea6326158fe",
"criteriaId": "9be6c6299cca48f597fe71bc99c37b2f",
"source": "type1",
},
{
"id_1": "1ecdf410b3314865be2b52ca9b4c8539",
"criteriaId": "9be6c6299cca48f597fe71bc99c37b2f",
"source": "type2",
}
]
},
{
"id": "b83b3f081a7b45e087183740b12faf3a",
"caption": "caption1",
"criteriaType": "type1",
"input": [
{
"id_1": "f46da7ffa859425e922bdbb701cfcf88",
"criteriaId": "b83b3f081a7b45e087183740b12faf3a",
"source": "type3",
},
{
"id_1": "abb87219db254d108a1e0f774f88dfb6",
"criteriaId": "b83b3f081a7b45e087183740b12faf3a",
"source": "type1",
}
]
},
{
"id": "fe5b071a2d8a4a9da61bbd81b9271e31",
"caption": "caption1",
"criteriaType": "type1",
"input": [
{
"id_1": "7ea1b85e4dbc44e8b37d1110b565a081",
"criteriaId": "fe5b071a2d8a4a9da61bbd81b9271e31",
"source": "type3",
},
{
"id_1": "c5f943b61f674265b8237bb560cbed03",
"criteriaId": "fe5b071a2d8a4a9da61bbd81b9271e31",
"source": "type3",
}
]
}];
function filterObj(obj, column, value){
var newArray = obj.filter(function (el) {
if(el[column]){
return el[column] == value;
}else{
for(var key in el.input){
if(typeof(el.input[key] == "object")){
var item = el.input[key];
if(item[column] == value){return item;}
}
}
}
});
return newArray;
}
console.log(filterObj(obj, 'caption','caption1'));
console.log(filterObj(obj, 'criteriaId','fe5b071a2d8a4a9da61bbd81b9271e31'));
console.log(filterObj(obj, 'id_1','1ecdf410b3314865be2b52ca9b4c8539'));
Upvotes: 0
Reputation: 1888
// if field has a value, filter on it, else return original json
const having = (json, field, val) =>
val ? json.filter(j => j[field] === val) : json
const filterBySource = (json, source) => {
if (!source) return json
return json.filter(
j => j.input.length > 0 && j.input.some(input => input.source === source)
)
}
function search(json, params = {}) {
const { objectId: id, ctype: criteriaType, inputSource: source } = params
// if no filters, return the whole json
if (!(id || criteriaType || source)) return json
let result
result = having(json, 'id', id)
result = having(result, 'criteriaType', criteriaType)
return filterBySource(result, source)
}
const params = {
objectId: 'fe5b071a2d8a4a9da61bbd81b9271e31',
ctype: 'type1',
inputSource: 'type3'
}
search(json, params).map(({ id, caption, criteriaType, input }) => {
// do something with filtered json
})
Upvotes: 0
Reputation: 1623
Lodash find and filter can be used for this. Find will be faster in nested array as compared to Filter it needs to match first occurrence.
json = ctype ? _.filter(json, function(o) {
return o.criteriaType === ctype;
}) || json;
json = objectId ? _.filter(json, function(o) {
return o.id === objectId;
}) || json;
json = source ? _.filter(json, function(o) {
return _.find(o.input, function(input_object) {
return input_object.source === source;
});
}) || json;
Upvotes: 0
Reputation: 4592
requirements are filters are optional, and none of the source matches parent shall not be returned https://jsfiddle.net/cpk18dt4/9/
Comments are in the code. hope it explains what the function does.
const fnFilter = (criteriaType, id, source) => {
let result = oData;
if (criteriaType) { // it can be null (optional)
result = result.filter(d => d.criteriaType === criteriaType);
}
if (id) { // it can be null (optional)
result = result.filter(d => d.id === id);
}
if (source) { // it can be null (optional)
result = result.filter(d => {
const inputs = d.input.filter(inp => inp.source === source);
// If none of the input.source match, the parent object should be filtered out
if (inputs.length === 0) {
return false;
}
d.input = inputs;
return true;
});
}
return result;
};
Upvotes: 1
Reputation: 16217
There are a couple approaches to this. You can implement this in pure JS, and I recommend Lodash:
1) Lodash filters
``` javascript
var users = [
{ 'user': 'barney', 'age': 36, 'active': true },
{ 'user': 'fred', 'age': 40, 'active': false }
];
_.filter(users, function(o) { return !o.active; });
// => objects for ['fred']
// The `_.matches` iteratee shorthand.
_.filter(users, { 'age': 36, 'active': true });
// => objects for ['barney']
// The `_.matchesProperty` iteratee shorthand.
_.filter(users, ['active', false]);
// => objects for ['fred']
// The `_.property` iteratee shorthand.
_.filter(users, 'active');
// => objects for ['barney']
```
2) JavaScript ES5 filter()
``` javascript
var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
var result = words
.filter(word => word.length > 6)
.filter(word => word.length < 8);
console.log(result);
// expected output: Array ["present"]
```
2) MapReduce
MapReduce is one of my favorite tools for working with sets/collections.
You used map()
in your code above. The trick might be to change map
to reduce
.
With map
, you get a 1-1 ratio of collection items in and out.
With reduce
, you get as many items as you like generated for each item in the input. E.g.
``` javascript
var stuff = ['couch', 'chair', 'desk'];
var hasFiveLetters = stuff.reduce((total, item) => {
if (item.length === 5) total.push(item); // add to total any items you like
return total; // don't forget to return total!
}, []); // initialize total to []
console.log(hasFiveLetters); // ['couch', 'chair'];
```
Upvotes: 1