Wednesday, February 26, 2014

Lodash Where Inclusive Or

I really like using the Lodash where() function for filtering arrays. Something about it makes for elegant, condensed code — two very big wins in my opinion. For example, you can pass complex conditions in an object that test for property value equality. Each property is "and"ded together. The where() function loses some of it's power when you want to combine expressions using "and" and "or". Often, the result is me writing a function to do the complex filtering, and passing that to where(). But there's another way to do it.

If the "or" condition is inclusive, the uniq() function can help you out. This let's you combine multiple where() filters using an "inclusive or". Let's say you have the following data.

var data = [
    { age: 23, gender: "male" },
    { age: 25, gender: "female" },
    { age: 25, gender: "male", active: true },
    { age: 26, gender: "female" },
    { age: 23, gender: "male" },
    { age: 25, gender: "female", active: true }
];

Now suppose we want to filter this collection by people why are either female, or, people who are 25 and active. Rather than write a where() filtering function, you could do something like what follows.

var result = _.uniq( ( [] ).concat(
    _.where( data, { gender: "female" } ),
    _.where( data, { age: 25, active: true } ) ) );

What we're doing here is constructing an array that is the result of two where() operations. The join is done by calling concat() on a new array. Now, since this is an inclusive "or", there may be some overlap between the two where() results. That means that there's duplicates in the resulting array, potentially. The last step is to tease these out using uniq().