madox2
madox2

Reputation: 51841

What is the best way to create simple filter functions in javascript?

Many times I face the same problem: I want to filter an array with a simple condition e.g. check for non/equality, greater than, less than, contains...

My code looks like this:

var result = [1, 2, 3, 4].filter(function(i) {
   return i > 2; 
});
console.log(result); // [3, 4]

It would by nice to have shortcuts to such a simple operations so I created some helper functions:

function isGreaterThan(value) {
    return function(original) {
        return value < original;
    }
}
[1, 2, 3, 4].filter(isGreaterThan(2)); // [3, 4]

or:

function isGreaterThan(value, original) {
    return value < original;
}
[1, 2, 3, 4].filter(isGreaterThan.bind(null, 2)); // [3, 4]

Is there a better way how to do this in javascript? Does javascript have any built-in functions to support these simple comparisions?

Upvotes: 8

Views: 814

Answers (3)

Mulan
Mulan

Reputation: 135207

I'll expand on @Avaq's answer a little bit here. You don't need a lib like Rambda to start using currying. You can start doing this with ES6 today.

It seems you already understand the concept here. This is already a curried function. (Each sequenced function takes only one argument)

function isGreaterThan(value) {
    return function(original) {
        return value < original;
    }
}

With ES6 arrow functions, this gets a lot easier.

const gt = x => y => y > x;

Notice how you flipped the the operator > to a < in your function to make the usage seem more natural? It's very common with curried functions to first take the operand that is least likely to change. With gt, I think it's better to use > here since that's the name of our function, but instead flip the operands. That's why you see me returning y > x instead of x > y. gt(5) returns a function y => y > 5, which feels very natural to me.

Without further ado, let's see it work in a filter

[1,2,3,4,5,6].filter(gt(3)); //=> [4,5,6]

If you need this to work in an ES5 environment, you can transpile it with babel very easily. The result should look very familiar

"use strict";
var gt = function gt(x) {
    return function (y) {
        return y > x;
    };
};

And with that, you're at the doorstep of functional programming. There's a ton of fun stuff to learn. With the kind of problem we discussed here, I think you'd be interested in learning about function composition next.

Here's a basic composition to whet your appetite

// filter out odd numbers
const mod = x => y => y % x;
const eq = x => y => y === x;
const comp = f => g => x => f(g(x));
const isEven = comp (eq (0)) (mod (2));
[1,2,3,4,5,6].filter(isEven); //=> [2,4,6]

Upvotes: 3

Avaq
Avaq

Reputation: 3031

Madox, what you've stumbled upon is the concept of currying! And you'll be glad to hear that there is an entire JavaScript community built around that idea. With Ramda your code would look like:

var filterSmallNumbers = filter(gte(3));
var smallNumbers = filterSmallNumbers([1,2,3,4,5,6]);

And it works.

All Ramda provides, is a list of "curried helper functions" like the one you showed. If you'd rather curry your own helper functions, then you might want a curry helper function which reduces the boilerplate: var isGreaterThan = curry(function(a, b){ return a > b }). This curry function is provided by most utility libraries like Underscore, Lodash or Ramda.

Upvotes: 4

leninhasda
leninhasda

Reputation: 1730

you were almost there, here is the correct one:

var original = 2;
function isGreaterThan(value) {
    return value > original;
}
var result = [1, 2, 3, 4].filter(isGreaterThan);
// result is [3, 4]

reference

Upvotes: -4

Related Questions