0

I know that the .reduce function in Javascript has a notion of previous and current variables "built-in", so to speak, in its definition. So I'm curious why this doesn't work:

var bigrams = [0, 1, 2, 3, 4].reduce(function(previous, current) {
  return [previous, current]
});

I do not think that means what I think it means, because now bigrams contains:

[[[[0,1],2],3],4]

When what I wanted was:

[[0,1],[1,2],[2,3],[3,4]]

I think it has to do with the fact that the result should be pushed into the accumlator (which should perhaps be an empty array, something like: arr.reduce(/*magic*/, [])?

  • Should I not be using .reduce to do this?
  • If so, is there another "functional" way to do it?
  • How do I avoid this nesting behavior?
  • It's a *reduce* (*fold*) function where `previous` is the *accumulator* (and shouldn't be named `previous`), not a map function that has access to its previous item. – Bergi Jan 19 '15 at 22:01

1 Answers1

4

The way reduce works is that the output of one call is used as the input to the next call. If we name your function f, your call is equivalent to:

f(f(f(f(0, 1), 2), 3), 4)

In other words, the previous does not mean "previous item in the original array", it means "result of the previous call to the function".

reduce is not a great choice for this task, because, as its name implies, it is aimed at reducing an array to a single value. One "functional" way to do this is to use zip and zip the array with its tail (all but the first element), as shown in this Haskell example. However, Javascript doesn't have a zip function builtin. Using the second zip implementation from this answer:

function zip() {
    var args = [].slice.call(arguments);
    var shortest = args.length==0 ? [] : args.reduce(function(a,b){
        return a.length<b.length ? a : b
    });

    return shortest.map(function(_,i){
        return args.map(function(array){return array[i]})
    });
}

You can do:

var x = [0, 1, 2, 3, 4]
zip(x, x.slice(1))

However, in JavaScript, I think most people would probably just do it iteratively, like in the answers to this question.

Community
  • 1
  • 1
BrenBarn
  • 242,874
  • 37
  • 412
  • 384