previous value in array block

J

Jason Lillywhite

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!
 
B

botp

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 =3D [1,3,3,2]
prev_item =3D 0
b =3D []

a.each do |item|
=A0b << item - prev_item
=A0prev_item =3D item
end

puts b

=3D> 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 =3D [1,3,3,2] =3D> [1, 3, 3, 2]
a.zip(a.dup.unshift(0)).map{|x,y| x-y}
=3D> [1, 2, 0, -1]

kind regards -botp
 
D

Deiva Rajasingam

Jason said:
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 - a[i-1])
end

puts b

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

-DR
 
H

Harry Kakueki

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 :)
Anyway, based on your code,

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

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


Harry
 
J

Jesús Gabriel y Galán

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 :)
Anyway, based on your code,

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

b = Array.new(a.length){|i| a-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.
 
S

steve

Jason said:
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!

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
 
X

Xavier Noria

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 }
 
D

David A. Black

Hi --

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

--
David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com
Q: What's the best way to get a really solid knowledge of Ruby?
A: Come to our Ruby training in Edison, New Jersey, September 14-17!
Instructors: David A. Black and Erik Kastner
More info and registration: http://rubyurl.com/vmzN
 
R

Robert Dober

each_cons seems natural here:

require 'enumerator'

a =3D [1, 3, 3, 2]
b =3D 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 }


--=20
Toutes les grandes personnes ont d=92abord =E9t=E9 des enfants, mais peu
d=92entre elles s=92en souviennent.

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

[Antoine de Saint-Exup=E9ry]
 
R

Robert Dober

Hi --

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 }
A beauty, sorry did not see it before my post!
Cheers
Robert
 
D

David A. Black

Hi --

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 }

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


David

--
David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com
Q: What's the best way to get a really solid knowledge of Ruby?
A: Come to our Ruby training in Edison, New Jersey, September 14-17!
Instructors: David A. Black and Erik Kastner
More info and registration: http://rubyurl.com/vmzN
 
R

Robert Dober

Hi --

each_cons seems natural here:

require 'enumerator'

a =3D [1, 3, 3, 2]
b =3D 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 }

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)
...

Robert
David

--
David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com
Q: What's the best way to get a really solid knowledge of Ruby?
A: Come to our Ruby training in Edison, New Jersey, September 14-17!
=A0 Instructors: David A. Black and Erik Kastner
=A0 More info and registration: http://rubyurl.com/vmzN



--=20
Toutes les grandes personnes ont d=92abord =E9t=E9 des enfants, mais peu
d=92entre elles s=92en souviennent.

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

[Antoine de Saint-Exup=E9ry]
 
D

David A. Black

Hi --

Hi --

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 }

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

--
David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com
Q: What's the best way to get a really solid knowledge of Ruby?
A: Come to our Ruby training in Edison, New Jersey, September 14-17!
Instructors: David A. Black and Erik Kastner
More info and registration: http://rubyurl.com/vmzN
 
R

Robert Dober

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
 
R

Rick DeNatale

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 }

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
 
D

David A. Black

Hi --

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

--
David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com
Q: What's the best way to get a really solid knowledge of Ruby?
A: Come to our Ruby training in Edison, New Jersey, September 14-17!
Instructors: David A. Black and Erik Kastner
More info and registration: http://rubyurl.com/vmzN
 
R

Robert Dober

Hi --

In 1.9 you get: enumerable.each_cons(x).map ... =A0which 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.
 
W

w_a_x_man

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!

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]
 
W

w_a_x_man

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!


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]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top