3

I was wondering what people think about using a reduce function vs loop for returning true if a condition exists.

Example:

var a = [1, 5, 7, 4, 2, 5, 3];

var greaterThan5 = a.reduce(function(prev, val) {
    return (prev || val > 5);
}, false);

vs

var greaterThan5 = false;
for(var i = 0; i < a.length; i++) {
    if(a[i] > 5) {
        greaterThan5 = true;
        break;
    }
}

vs

var i = 0;
var greaterThan5 = false;
while(!greaterThan5 && i < a.length) {
    greaterThan5 = (a[i] > 5);
    i++;
}

The for loop and while loop will exit when the condition is true, but I think the reduce syntax is easier to read and gives less room for run-time errors.

1
  • 1
    In terms of functional programming, most functional languages don't have for or while loops. Indeed they don't have any control structure syntax. Only functions.
    – slebetman
    Aug 15 '15 at 10:55
16

First of all, why not use Array.prototype.some(), which seems to perfectly match what you're actually trying to do.

The some() method tests whether some element in the array passes the test implemented by the provided function.

Of course, that doesn't really answer your question: whether to use the for loop, or the call to Array.protoype.reduce()? Let me also try to answer that. The question is mostly regarding weighing performance against clarity of code.

For performance: measure, not just using random arrays, but using arrays that make sense in your project. No need in selecting a method that works fast on 1,000,000 element arrays, when all you need to process are arrays of up to 10 elements.

More importantly, only worry about performance when performance is an issue.

With respect to clarity. I actually think the explicit for-loop is more clear than the Array.prototype.reduce(). But, what matters most is, what the people on your team will find the most clear. If one of your team finds an explicit for-loop more clear, it's probably better to use that, if only because it uses a less advanced set of features.

5
  • 1
    .reduce() offers an opportunity to expose colleagues to the greater set of tools - its also standard since 2011 or there about(s) so short of something like a necessity for that sort of legacy support - it could be novel given the argument spec. some() also accomplishes the novelty with the same service agreement, of course. love it. Aug 15 '15 at 7:04
  • 4
    I personally find reduce() unclear in this example because, as you point out, reduce() is not what the OP actually wants to do. some() definitely beats all of the above.
    – Ixrec
    Aug 15 '15 at 10:39
  • what the people on your time will find the most clear a bit hard to understand. Is time a typo for team?
    – Caridorc
    Aug 15 '15 at 11:02
  • 1
    Also be aware of Array.prototype.every for the and version of the short-circuiting reduce.
    – Darkhogg
    Aug 15 '15 at 11:25
  • 1
    @Caridorc: yes, it was a typo. Darkhogg corrected it now. Aug 15 '15 at 13:40
5

For most functional languages, neither.

There is usually a reducing function which short circuts as you want it to.

In F# this is List.exists so you example would be

List.exists (fun x -> x > 5) a

In Haskell (with partial application of > to make a point free solution)

any (> 5) a
5
  • The above example could be written even shorter with the pointfree style as List.exists ((>)5) a Aug 15 '15 at 6:38
  • thank you. I found that javascript has the Array.prototype.some() function that does the same thing.
    – Tony Brix
    Aug 15 '15 at 6:40
  • @OverlyExcessive i dont think that will do what you think it will, that will bind the first argument of > to 5 i.e. you will be checking 5 > x
    – jk.
    Aug 15 '15 at 6:42
  • @jk Right, but if you reverse the comparison it will give the same results as the lambda. Aug 15 '15 at 6:46
  • @OverlyExcessive yes i take your point - added point free haskell version - as f# doesnt appeat to have away to do this without changing the operator i'd argue that it hurts readability there
    – jk.
    Aug 15 '15 at 7:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.