Previous value in array block

Is this a good way to use a previous value in an array block?

I want to subtract the item(i) from item(i-1) of the array, a and return
a new array of the results. Below is my attempt.

a = [1,3,3,2]
prev_item = 0
b = []

a.each do |item|
b << item - prev_item
prev_item = item
end

puts b

=> 1,2,0,-1

I’m thinking there must be a more elegant way of doing this.

thank you!

On Wed, Jul 29, 2009 at 11:39 AM, Jason
Lillywhite[email protected] wrote:

b << item - prev_item
prev_item = item
end

puts b

=> 1,2,0,-1

I’m thinking there must be a more elegant way of doing this.

to me, your code is elegant enough.
not sure if making code shorter would make it more, so…

a = [1,3,3,2]
=> [1, 3, 3, 2]
a.zip(a.dup.unshift(0)).map{|x,y| x-y}
=> [1, 2, 0, -1]

kind regards -botp

Jason L. wrote:

a = [1,3,3,2]
prev_item = 0
b = []

a.each do |item|
b << item - prev_item
prev_item = item
end

puts b

=> 1,2,0,-1

Another way could be:

a = [1,3,3,2]
b = [a[0]]

for i in 1…(a.length)
b << (a[i] - a[i-1])
end

puts b

Not sure if that can be considered elegant though. :slight_smile:

-DR

I want to subtract the item(i) from item(i-1) of the array, a and return
a new array of the results. Below is my attempt.

But, you are doing the opposite :slight_smile:
Anyway, based on your code,

FWIW, here is another one-liner.
Elegant? I don’t know.

b = Array.new(a.length){|i| a[i]-a[i-1]}[1…-1].unshift(a[0])

Harry

On Wed, Jul 29, 2009 at 8:18 AM, Harry K.[email protected]
wrote:

Elegant? I don’t know.

b = Array.new(a.length){|i| a[i]-a[i-1]}[1…-1].unshift(a[0])

Another way:

irb(main):001:0> a = [10,20,30,40]
irb(main):014:0> b = []
=> []
irb(main):015:0> a.each_with_index {|x,y| b << (y > 0? (x - a[y-1]): x)}
=> [10, 20, 30, 40]

irb(main):019:0> b
=> [10, 10, 10, 10]

Jesus.

each_cons seems natural here:

require ‘enumerator’

a = [1, 3, 3, 2]
b = a[0, 1]

a.each_cons(2) { |x, y| b << y - x }

Hi –

On Wed, 29 Jul 2009, Xavier N. wrote:

each_cons seems natural here:

require ‘enumerator’

a = [1, 3, 3, 2]
b = a[0, 1]

a.each_cons(2) { |x, y| b << y - x }

Here’s a 1.9 way, probably guilty of gross wasteage (by creating an
extra new array) but kind of cool:

[0,*a].each_cons(2).map {|x,y| y - x }

David

On Wed, Jul 29, 2009 at 10:50 AM, Xavier N.[email protected] wrote:

each_cons seems natural here:

require ‘enumerator’

a = [1, 3, 3, 2]
b = a[0, 1]

a.each_cons(2) { |x, y| b << y - x }
and purely functional
( [0] + a ).each_cons( 2 ).map{ |x,y| y -x }
or with Tom’s map arity trick implemented
( [0] + a ).map{ | x, y | y - x }


Toutes les grandes personnes ont d’abord été des enfants, mais peu
d’entre elles s’en souviennent.

All adults have been children first, but not many remember.

[Antoine de Saint-Exupéry]

On Wed, Jul 29, 2009 at 12:56 PM, David A. Black[email protected]
wrote:

a.each_cons(2) { |x, y| b << y - x }

Here’s a 1.9 way, probably guilty of gross wasteage (by creating an
extra new array) but kind of cool:

[0,*a].each_cons(2).map {|x,y| y - x }
A beauty, sorry did not see it before my post!
Cheers
Robert

Jason L. wrote:

b << item - prev_item
prev_item = item
end

puts b

=> 1,2,0,-1

I’m thinking there must be a more elegant way of doing this.

thank you!

I was recently reading through the facets docuementation and so thought
I would develop a solution for the OP using the elementwise method that
facets supplies. However while other facets methods from enumerable are
available, elementwise does not seem to be.

C:\Documents and Settings\Administrator>irb
irb(main):001:0> a=Array.new
=> []
irb(main):002:0> a.respond_to?(“elementwise”)
=> false
irb(main):003:0> a.respond_to?(“entropy”)
=> false
irb(main):004:0> require “facets”
=> true
irb(main):005:0> a.respond_to?(“entropy”)
=> true
irb(main):006:0> a.respond_to?(“elementwise”)
=> false

I am using windows xp, one click Ruby 186-26 and facets 2.5.0.

Can some kind person point out my error?

Thanks

Steve

Hi –

On Wed, 29 Jul 2009, Robert D. wrote:

( [0] + a ).each_cons( 2 ).map{ |x,y| y -x }
or with Tom’s map arity trick implemented
( [0] + a ).map{ | x, y | y - x }

I don’t understand that last one. Is this some kind of override of map
that turns it into each_cons + map?

David

On Wed, Jul 29, 2009 at 2:16 PM, David A. Black[email protected]
wrote:

a = [1, 3, 3, 2]
that turns it into each_cons + map?
IIRC it was like this

module Enumerable
method_alias :map, map
def map &blk
return map(&blk) if blk.arity < 2
each_cons( blk.arity).map(&blk)

Robert


Toutes les grandes personnes ont d’abord été des enfants, mais peu
d’entre elles s’en souviennent.

All adults have been children first, but not many remember.

[Antoine de Saint-Exupéry]

Hi –

On Wed, 29 Jul 2009, Robert D. wrote:

I don’t understand that last one. Is this some kind of override of map
that turns it into each_cons + map?
IIRC it was like this

module Enumerable
method_alias :map, map
def map &blk
return map(&blk) if blk.arity < 2
each_cons( blk.arity).map(&blk)

I confess I don’t see the point, but thanks for clarifying.

David

On Wed, Jul 29, 2009 at 2:31 PM, David A. Black[email protected]
wrote:

I confess I don’t see the point, but thanks for clarifying.
It is cheating, bending Ruby to the needs of the problem. We even had
a discussion if it should use each_cons or each_slice below the hood.

But the point might be, that it might make sense to have things like
map_cons or map_slice
I can only think about Ruby code, writing it, sorry.
Gotta look into Facets for that.

Cheers
Robert

On Wed, Jul 29, 2009 at 8:11 PM, Robert D.[email protected]
wrote:

or with Tom’s map arity trick implemented
( [0] + a ).map{ | x, y | y - x }

very cool.
thanks for the tip.

kind regards -botp

On Wed, Jul 29, 2009 at 8:11 AM, Robert D.[email protected]
wrote:

( [0] + a ).each_cons( 2 ).map{ |x,y| y -x }
Here’s a lisp/scheme inspired approach using inject and with an array
serving as a “cons cell” and first => car and last => cdr:

[1, 3, 3, 2].inject([0, []]) { |memo, elem| [elem, memo.last << (elem

  • memo.first)] }.last # => [1, 2, 0, -1]


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Hi –

On Wed, 29 Jul 2009, Robert D. wrote:

On Wed, Jul 29, 2009 at 2:31 PM, David A. Black[email protected] wrote:

I confess I don’t see the point, but thanks for clarifying.
It is cheating, bending Ruby to the needs of the problem. We even had
a discussion if it should use each_cons or each_slice below the hood.

But the point might be, that it might make sense to have things like
map_cons or map_slice

In 1.9 you get: enumerable.each_cons(x).map … which has much the
same effect. I don’t like the idea of map having a stealth each_cons
in it. Also, defining it for Enumerable won’t affect arrays (at least
in MRI), because Array overries map.

David

On Wed, Jul 29, 2009 at 3:20 PM, David A. Black[email protected]
wrote:

But the point might be, that it might make sense to have things like
map_cons or map_slice

In 1.9 you get: enumerable.each_cons(x).map … which has much the
same effect. I don’t like the idea of map having a stealth each_cons
in it. Also, defining it for Enumerable won’t affect arrays (at least
in MRI), because Array overries map.

yes we should not confuse, playing around and changing the language. I
have sometimes the feeling that people get nervous when I do this
“cheating” stuff, but if I meant this to be in Ruby I would say so and
probably at Ruby core. No it is just for the fun and elegance.
R.

On Jul 28, 10:39 pm, Jason L. [email protected]
wrote:

b << item - prev_item

Posted viahttp://www.ruby-forum.com/.

Never forget: we don’t need no stinkin’ loops!

x = 2,3,5,8,13
p x.zip( [0] + x ).map{|a,b| a-b}

=> [2, 1, 2, 3, 5]

On Jul 28, 10:39 pm, Jason L. [email protected]
wrote:

b << item - prev_item

Posted viahttp://www.ruby-forum.com/.

Never forget: we don’t need no stinkin’ loops!

x = 2,3,5,8,13
p x.zip( [0] + x ).map{|a,b| a-b}

=> [2, 1, 2, 3, 5]