0

I have a javascript object, that could be something like this

{
    "users": [{
        "id": "52",
        "name": "User name one",
        "profile": "student",
        "statusId": 1
    },...

I want to modify this object's properties given a set of parameters. Basically I want a new object which properties could match a set of constraints - a filter object - with this form (empty filter):

    var userFilter = {
        id : "",
        name: "",
        profile : "",
        state : ""
    };

I've seen the Array.prototype.filter, but can't figure a clean and generic way to use all properties of filter. I've tried this approach with a javascript string that concats all filters and using eval(), but I don't like this approach. Any suggestion ?

Thanks in advance, regards

1 Answer 1

2

You can use something like this to compare two Javascript objects:

// returns true if "obj" contains "other" as a subset
contains = function(obj, other) {
    return Object.keys(other).every(function(key) {
        return other[key] == obj[key];
    });
}

for example, contains(users[0], {profile: 'student'} ) returns true.

Once we have this, the rest is easy:

 userFilter = { ...criteria... }
 results = users.filter(function(item) { return contains(item, userFilter) })

Note that this does AND matching, that is, if the filter is {state:5, profile:'student'}, it finds records that have both state=5 and profile=student. To do OR matching instead, replace every() with some() in the above code.

As per your comment, the above function can be generalized by adding a comparison function as a parameter:

contains = function(obj, other, compare) {
    return Object.keys(other).every(function(key) {
        return compare ? compare(key, obj[key], other[key]) 
            : obj[key] == other[key];
    });
}

Comparison function accepts key, object value and filter value and is supposed to return true or false. Example:

user =  {
       "id": "52",
       "name": "Foo Bar"
}

// this uses the default "equals" comparison and fails
contains(user, { name: "Foo" });

// this uses a custom "indexOf" comparison and succeeds 
contains(user, { name: "Foo" }, function(key, val, flt) {
    return val.indexOf(flt) >= 0;
});
Sign up to request clarification or add additional context in comments.

1 Comment

Good approach. I can't test for equal object though, ie. for id I will have to find an exact match, but the name should be if the 'obj' contains the words of 'other'. I think I'll have to have 2 'contains' functions

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.