Kunal Vashist
Kunal Vashist

Reputation: 2471

How to Get the filter result from array object in javascript?

I am trying to get the filter result out from the json where the matched is true.

{
        "cat": [
            {
                "volume": "one",
                "category": [
                    {
                        "name": "Alpha",
                        "matched": true
                    },
                    {
                        "name": "Gamma",
                        "matched": false
                    }
                ]
            },
            {
                "volume": "two",
                "category": [
                    {
                        "name": "Beta",
                        "matched": false
                    },
                    {
                        "name": "Treta",
                        "matched": true
                    },
                    {
                        "name": "Neutral",
                        "matched": false
                    }
                ]
            },
            {
                "volume": "three",
                "category": [
                    {
                        "name": "Retro",
                        "matched": false
                    },
                    {
                        "name": "Jazz",
                        "matched": true
                    },
                    {
                        "name": "Rock",
                        "matched": false
                    },
                    {
                        "name": "Soft",
                        "matched": false
                    }
                ]
            }
        ]
}

Used Javascript filter

var jsonwant = jsonusing.cat.filter(function(e){
    return e.category.filter(function(e1){
        return e1.matched === true;
});
});

Js Fiddle for same

http://jsfiddle.net/xjdfaey3/

Result Should Come as

"cat": [
                {
                    "volume": "one",
                    "category": [
                        {
                            "name": "Alpha",
                            "matched": true
                        }
                    ]
                },
                {
                    "volume": "two",
                    "category": [
                        {
                            "name": "Treta",
                            "matched": true
                        }
                    ]
                },
                {
                    "volume": "three",
                    "category": [
                        {
                            "name": "Jazz",
                            "matched": true
                        }
                    ]
                }
            ]

but it is returning entire object.

Upvotes: 3

Views: 2074

Answers (2)

Scott Sauyet
Scott Sauyet

Reputation: 50787

I like the answer from @dsfq. It is probably as good as you will get using simple Javascript without a library. But I work on a JS functional programming library, Ramda, and that offers tools to make problems like this more tractable. Here is a one-line function to do this using Ramda:

evolve({'cat': map(evolve({category: filter(whereEq({'matched': true}))}))});

Explanation

whereEq accepts a template object and returns a predicate function that will take another object and check whether this new object has the same values for the keys of the template object. We pass it {'matched': true} so it accepts an object and checks whether this object has a 'matched' property with the value true. (This is oversimplified a bit. The function, like most Ramda functions actually is automatically curried, and would accept the test object initially, but since we don't supply one, it simply returns a new function that is expecting it. All the functions below act the same way, and I won't mention it for each.)

The function generated by whereEq is passed to filter. Filter accepts a predicate function (one which tests its input and returns true or false) and returns a function which accepts a list of objects, returning a new lists consisting of only those ones for which the function returned true.

Using this, we create an object to pass to evolve. This function accepts a configuration object that maps property objects to transformation functions. It returns a new function that accepts an object and returns a copy of it, except where transformation functions have been declared in the configuration object. There it returns the result of running that transformation against the data from the object. In our case, it will run the filter we've just built against the category property.

The function generated here is passed to map, which takes a function and returns a new function that accepts a list and returns the result of applying that function to every element of the list. Here that will end up being the collection of volumes.

Now the result of this map call is passed to evolve again for the property 'cat' of the outermost object. This is the final function. You can see it in action in the Ramda REPL.


I'm not trying to claim that this is inherently better. But tools that help you look at problems from a higher level of abstraction often let you write more succinct code.

Upvotes: 4

dfsq
dfsq

Reputation: 193261

You also need to modify internal category array after filtering:

var jsonwant = jsonusing.cat.filter(function(e){
    return (e.category = e.category.filter(function(e1){
        return e1.matched === true;
    })).length;
});

Note, that this will modify original object too.

UPD. In order to preserve original structure one more mapping step is needed to create new array:

var jsonwant = jsonusing.cat.map(function(e) {
    return {
        volume: e.volume,
        category: e.category.filter(function(e1){
            return e1.matched === true;
        })
    };
})
.filter(function(e) {
    return e.category.length;
});

Upvotes: 3

Related Questions