2

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

1
  • look my answer below Commented Jul 26, 2018 at 9:20

5 Answers 5

1

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;
};
Sign up to request clarification or add additional context in comments.

2 Comments

From this solution, I understood the actual problem.
Thanks a lot :) Lemme work more on it and see if it could be optimized more.
1

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'];

```

1 Comment

I can't use lodash, I did lookup multiple filters chaining - but didn't succeed. also can't use lodash :(
0

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;

Comments

0
// 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
})

Comments

0

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'));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.