Search code examples
javascriptjsonbackbone.jslambda

lambda like matching on json object for javascript backbone?


not a front end SME....is there a javascript or backbone(_) equivalent of this java 8 lambda instead of looping over a JSON array and matching on "type"? :

{
  "things": [
    {
      "type": "THE_OTHER_THING"
    },
    {
      "type": "MY_THING"
    }
  ]
}

.

thing theThing =  things.stream().filter(x -> x.getType() == ThingType.MY_THING).findFirst().orElse(null);

Solution

  • Assuming you are looking to iterate through an array and only return objects with a given type, I would suggest the following:

    For single or little use, you could simply create the function that asserts the type of your choice:

    function isThing(jsonObject) {
        return jsonObject.type === "THIS_THING";
    }
    

    Or to avoid hard coding:

    var THING_TYPE = "THIS_THING";
    function isThing(jsonObject) {
        return jsonObject.type === THING_TYPE;
    }
    

    Then you can apply this function to an array using its filter method.

    var filteredList = completeList.filter(isThing);
    

    filter, as described on MDN Array.prototype.filter, takes a function as an argument and applies it to every element within the array. If the function returns true, the element is added to a new array. Once the passed function has been applied to each element, the filter function returns the new array.

    The above choice may be practical if you are simply looking for one or two types. However, if you have many types for which you might want filters, you should consider abstracting this away slightly, like so:

    function createFilterWithType(desiredType) {
        // will return true if jsonObject is of desired type
        var typeAsserter = function (jsonObject) {
            return jsonObject.type === desiredType;
        }
    
        return typeAsserter;
    }
    
    
    // Create functions that assert if object is given type    
    var isThisThingType = createFilterWithType("THIS_THING");
    var isOtherThingType = createFilterWithType("OTHER_THING");
    
    // Data
    var completeList = [
       {type:"THIS_THING", id:0},
       {type:"OTHER_THING", id:1}
    ];
    
    // Data filtered by applying asserters to completeList
    var thingTypeList = completeList.filter(isThisThingType);
    // returns [{type:"THIS_THING", id:0}]
    
    var otherTypeList = completeList.filter(isOtherThingType);
    // returns [{type:"OTHER_THING", id:1}]
    

    Alternatively, you can create the asserters and apply in a single step:

    var thingTypeList = completeList.filter(createFilterWithType("THIS_THING"));
    var otherTypeList = completeList.filter(createFilterWithType("OTHER_THING"));
    

    Though you remove a few lines by doing so, you lose in performance as each invocation of filter requires the creation of the anonymous assertion function. Worse still, compacting your code this way can make it far more difficult to reason about.