Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

First order array difference in Ruby

Tags:

ruby

What's the slickest, most Ruby-like way to do this?

[1, 3, 10, 5].diff

should produce

[2, 7, -5]

that is, an array of first order differences. I've come up with a solution which I'll add below, but it requires ruby 1.9 and isn't all that slick. what else is possible?

like image 630
Peter Avatar asked Oct 17 '09 10:10

Peter


1 Answers

I like this functional style:

module Enumerable
  def diff
    each_cons(2).map {|pair| pair.reverse.reduce :-}
  end
end

EDIT: I just realized that the reverse is totally unnecessary. If this were a functional language, I would have used pattern matching, but Ruby doesn't support pattern matching. It does, however, support destructuring bind, which is a good enough approximation for pattern matching in this case.

each_cons(2).map {|first, second| second - first}

No smiley, though.

I like how this sounds if you just read it out loud from left to right: "For each pair, apply the difference between the first and second elements of the pair." In fact, I normally don't like the name collect and prefer map instead, but in this case that reads even better:

each_cons(2).collect {|first, second| second - first}

"For each pair, collect the difference between its elements." Sounds almost like a definition of first order difference.

like image 155
Jörg W Mittag Avatar answered Oct 13 '22 13:10

Jörg W Mittag