[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

How does Array.map work for 2D arrays?

karthik.nar

1/14/2007 10:22:00 AM

I was reading this example:

pt = [ [ "Check", "check" ], [ "Credit card", "cc" ], [ "Purchase
order", "po" ] ]
pt.map {|value| value}

Displays the 2D Array elements as expected => [["Check", "check"],
["Credit card", "cc"], ["Purchase order", "po"]]

but a two-parameter block suppled to map like below:

>> pt.map {|disp, value| value}
=> ["check", "cc", "po"]

is able to give me the second element of the 2D array.

i looked in the ruby doc and on the net for examples, but 2D arrays are
typically not covered.

while, i love this functionality, my question is -

How does this 2 parameter variant really work?

How does the array.map "figure out" and pass disp to param1 and value to
param2?

--
Posted via http://www.ruby-....

5 Answers

Robert Klemme

1/14/2007 10:45:00 AM

0

On 14.01.2007 11:21, Karthik Nar wrote:
> I was reading this example:
>
> pt = [ [ "Check", "check" ], [ "Credit card", "cc" ], [ "Purchase
> order", "po" ] ]
> pt.map {|value| value}
>
> Displays the 2D Array elements as expected => [["Check", "check"],
> ["Credit card", "cc"], ["Purchase order", "po"]]
>
> but a two-parameter block suppled to map like below:
>
>>> pt.map {|disp, value| value}
> => ["check", "cc", "po"]
>
> is able to give me the second element of the 2D array.
>
> i looked in the ruby doc and on the net for examples, but 2D arrays are
> typically not covered.
>
> while, i love this functionality, my question is -
>
> How does this 2 parameter variant really work?
>
> How does the array.map "figure out" and pass disp to param1 and value to
> param2?

It doesn't really have to do anything at all:

irb(main):001:0> def foo() yield 1,2 end
=> nil
irb(main):002:0> foo {|a| p a}
(irb):2: warning: multiple values for a block parameter (2 for 1)
from (irb):1
[1, 2]
=> nil
irb(main):003:0> foo {|*a| p a}
[1, 2]
=> nil
irb(main):004:0> foo {|a,b| p a}
1
=> nil
irb(main):005:0> def foo() yield [1,2] end
=> nil
irb(main):006:0> foo {|a| p a}
[1, 2]
=> nil
irb(main):007:0> foo {|*a| p a}
[[1, 2]]
=> nil
irb(main):008:0> foo {|a,b| p a}
1
=> nil

You see in line 6 and 8 how it works.

However, map could also evaluate the block's arity:

irb(main):009:0> def foo(&b) p b.arity; b[1,2] end
=> nil
irb(main):010:0> foo {|a| p a}
1
(irb):10: warning: multiple values for a block parameter (2 for 1)
from (irb):9
[1, 2]
=> nil
irb(main):011:0> foo {|a,b| p a}
2
1
=> nil
irb(main):012:0> foo {|*a| p a}
-1
[1, 2]
=> nil
irb(main):013:0> def foo(&b) p b.arity; b[[1,2]] end
=> nil
irb(main):014:0> foo {|a| p a}
1
[1, 2]
=> nil
irb(main):015:0> foo {|a,b| p a}
2
1
=> nil
irb(main):016:0> foo {|*a| p a}
-1
[[1, 2]]
=> nil

HTH

robert

karthik.nar

1/14/2007 11:50:00 AM

0

wow, robert, that makes a lot of sense Thanks !

now my next question: how would a newbie (like me) know by looking at
the ruby doc that Array.map could actually support 2D arrays in this
fashion?

(or is it that it just becomes "obvious" as one uses Ruby more and
more?!)


Robert Klemme wrote:
>
> It doesn't really have to do anything at all:
>
> irb(main):001:0> def foo() yield 1,2 end
> => nil
> irb(main):002:0> foo {|a| p a}
> (irb):2: warning: multiple values for a block parameter (2 for 1)
> from (irb):1
> [1, 2]
> => nil
> irb(main):003:0> foo {|*a| p a}
> [1, 2]
> => nil
> irb(main):004:0> foo {|a,b| p a}
> 1
> => nil
> irb(main):005:0> def foo() yield [1,2] end
> => nil
> irb(main):006:0> foo {|a| p a}
> [1, 2]
> => nil
> irb(main):007:0> foo {|*a| p a}
> [[1, 2]]
> => nil
> irb(main):008:0> foo {|a,b| p a}
> 1
> => nil
>
> You see in line 6 and 8 how it works.
>
> However, map could also evaluate the block's arity:
>
> irb(main):009:0> def foo(&b) p b.arity; b[1,2] end
> => nil
> irb(main):010:0> foo {|a| p a}
> 1
> (irb):10: warning: multiple values for a block parameter (2 for 1)
> from (irb):9
> [1, 2]
> => nil
> irb(main):011:0> foo {|a,b| p a}
> 2
> 1
> => nil
> irb(main):012:0> foo {|*a| p a}
> -1
> [1, 2]
> => nil
> irb(main):013:0> def foo(&b) p b.arity; b[[1,2]] end
> => nil
> irb(main):014:0> foo {|a| p a}
> 1
> [1, 2]
> => nil
> irb(main):015:0> foo {|a,b| p a}
> 2
> 1
> => nil
> irb(main):016:0> foo {|*a| p a}
> -1
> [[1, 2]]
> => nil
>
> HTH
>
> robert

Robert Klemme

1/14/2007 12:41:00 PM

0

On 14.01.2007 12:49, karthik wrote:
> wow, robert, that makes a lot of sense Thanks !

You're welcome!

> now my next question: how would a newbie (like me) know by looking at
> the ruby doc that Array.map could actually support 2D arrays in this
> fashion?
>
> (or is it that it just becomes "obvious" as one uses Ruby more and
> more?!)

I guess the latter. What you see is basically the effect of a
combination of features: You're actually not dealing with a 2D Array but
with an Array that contains Arrays, or more generally, an Enumerable
that contains Enumerables. A true 2D Array would make sure that every
row has the same number of elements and similarly for columns, that's
why it's not a 2D Array. The other aspect is how yield and assignments
work. There is some automatic, err, how would you call that, unrolling?

irb(main):001:0> a,b=1,2
=> [1, 2]
irb(main):002:0> a
=> 1
irb(main):003:0> b
=> 2
irb(main):004:0> a,b=[1,2]
=> [1, 2]
irb(main):005:0> a
=> 1
irb(main):006:0> b
=> 2

So, an Array is automatically assigned element wise you do not need to
explicitly provide the splat operator:

irb(main):007:0> a,b=*[1,2]
=> [1, 2]
irb(main):008:0> a
=> 1
irb(main):009:0> b
=> 2

You can do a lot more fancy stuff with this as Ruby actually does
pattern matching:

irb(main):001:0> a,b,c=1,[2,3]
=> [1, [2, 3]]
irb(main):002:0> a
=> 1
irb(main):003:0> b
=> [2, 3]
irb(main):004:0> c
=> nil
irb(main):005:0> a,(b,c)=1,[2,3]
=> [1, [2, 3]]
irb(main):006:0> a
=> 1
irb(main):007:0> b
=> 2
irb(main):008:0> c
=> 3

This is often useful when using #inject on a Hash:

$ irb
irb(main):001:0> h={}
=> {}
irb(main):002:0> 10.times { i=rand(10); h[i]=10-i}
=> 10
irb(main):003:0> h
=> {0=>10, 6=>4, 7=>3, 2=>8, 8=>2, 3=>7, 9=>1, 4=>6}
irb(main):004:0> h.size
=> 8
irb(main):005:0> h.inject(0) {|sum,(key,val)| sum + key + val}
=> 80

This is of course a silly example. I chose these values in order to
make checking what's going on easier (i.e. summing all keys and values
equals h.size * 10).

Kind regards

robert

Daniel Waite

1/15/2007 8:33:00 AM

0

Karthik Nar wrote:
> ... a two-parameter block suppled to map like below:
>
>>> pt.map {|disp, value| value}
> => ["check", "cc", "po"]
>
> is able to give me the second element of the 2D array.
>
> while, i love this functionality, my question is -
>
> How does this 2 parameter variant really work?
>
> How does the array.map "figure out" and pass disp to param1 and value to
> param2?

Two points. First, I don't know how it figures it out. Second, your
question can be "answered" by looking at another example...

a = [ [ 'billy', 'goat', 'cheese' ], [ 'silly', 'hats' ] ]

a.map { |x, y, z| z } # => ["cheese", nil]

Observation tells us that map isn't really figuring out that you have a
2D array, it's simply assuming that if you're asking for two arguments
(or three or one-hundred), that your array has them.

Make sense?

--
Posted via http://www.ruby-....

karthik.nar

1/15/2007 9:38:00 AM

0

yes makes sense!!

here's some experiments i did, and it's more of a ruby thing than a map
thing!

irb(main):001:0> a = 1, 2
=> [1, 2]

irb(main):002:0> def map(a) yield a end
=> nil

irb(main):003:0> map(a) { | x, y | p y }
2
=> nil

irb(main):004:0> map(a) {| x | p x }
[1, 2]
=> nil


> Two points. First, I don't know how it figures it out. Second, your
> question can be "answered" by looking at another example...
>
> a = [ [ 'billy', 'goat', 'cheese' ], [ 'silly', 'hats' ] ]
>
> a.map { |x, y, z| z } # => ["cheese", nil]
>
> Observation tells us that map isn't really figuring out that you have a
> 2D array, it's simply assuming that if you're asking for two arguments
> (or three or one-hundred), that your array has them.
>
> Make sense?


--
Posted via http://www.ruby-....