[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Stupid question from a Ruby newb

Will

1/11/2006 4:32:00 AM

Hi folks, I know that this is a really simple question, and there must
be many ways to do it in Ruby... but what I'm looking for is an
elegant way to take a collection of objects and create a hash mapping
one attribute of the object as the key and the other as the value. So
far what I am doing is this:

objects = some_method_to_return_collect( method_params )
myHash = Hash.new

@objects.each do |object|
myHash[ object.key ] = object.value
end

I played around with doing something like:

@myHash = objects.map do |object| [ object.key => object.value ] end

But that returns an array of single-value hashes, which is not exactly
what I am trying to do.

I know this is a stupid question, and probably pointless because I do
know ways to do it, but I would really like the know the Ruby Way to do
this. Ruby seems so given to elegant code that my code above really
bugs me for some reason.

Thanks all!

-Will

10 Answers

David Vallner

1/11/2006 4:42:00 AM

0

Will wrote:

>Hi folks, I know that this is a really simple question, and there must
>be many ways to do it in Ruby... but what I'm looking for is an
>elegant way to take a collection of objects and create a hash mapping
>one attribute of the object as the key and the other as the value. So
>far what I am doing is this:
>
>objects = some_method_to_return_collect( method_params )
>myHash = Hash.new
>
>@objects.each do |object|
> myHash[ object.key ] = object.value
>end
>
>I played around with doing something like:
>
>@myHash = objects.map do |object| [ object.key => object.value ] end
>
>But that returns an array of single-value hashes, which is not exactly
>what I am trying to do.
>
>I know this is a stupid question, and probably pointless because I do
>know ways to do it, but I would really like the know the Ruby Way to do
>this. Ruby seems so given to elegant code that my code above really
>bugs me for some reason.
>
>Thanks all!
>
>-Will
>
>
>
>
There are no stupid questions, only stupid people.

The solution you first wrote where you're iterating over the array is as
good as any, i would probably use that.

If you like Ever So Cool one-liners, this one might also work:

myHash = objects.inject({}){|hash, item| hash[item.key] =
item.value; hash}

It does pretty much completely the same, except were this Smalltalk, the
block wouldn't be a closure and therefore a horse's butthair more
memory-efficient solution.

David Vallner


Steve Litt

1/11/2006 4:49:00 AM

0

On Tuesday 10 January 2006 11:42 pm, David Vallner wrote:
[clip]
> There are no stupid questions, only stupid people.

I think what David means here is that failure to ask the question is
stupid :-)

SteveT

Steve Litt
http://www.troublesh...
slitt@troubleshooters.com


David Vallner

1/11/2006 4:56:00 AM

0

Steve Litt wrote:

>On Tuesday 10 January 2006 11:42 pm, David Vallner wrote:
>[clip]
>
>
>>There are no stupid questions, only stupid people.
>>
>>
>
>I think what David means here is that failure to ask the question is
>stupid :-)
>
>SteveT
>
>Steve Litt
>http://www.troublesh...
>slitt@troubleshooters.com
>
>
>
Oh, not quite, that was just a general random piece of Zen. (read: brain
fart).
But indeed -part- of the meaning was that you can't indeed ask stupid
questions. For given values of 'question' ;P

Green eggs and spam.

David Vallner
Shouldn't turn Thunderbird on when insomniac...


Gary Wright

1/11/2006 5:04:00 AM

0


On Jan 10, 2006, at 11:42 PM, David Vallner wrote:

> If you like Ever So Cool one-liners, this one might also work:
>
> myHash = objects.inject({}){|hash, item| hash[item.key] =
> item.value; hash}
>
> It does pretty much completely the same, except were this
> Smalltalk, the block wouldn't be a closure and therefore a horse's
> butthair more memory-efficient solution.
>

Is this because the Smalltalk compiler will notice that there are no
references to variables outside the block and Ruby's current
implementation
will not notice the same thing?


Gary Wright





Ara.T.Howard

1/11/2006 5:13:00 AM

0

David Vallner

1/11/2006 6:17:00 AM

0

ara.t.howard@noaa.gov wrote:

>
> h = objects.inject({}){|h,o| h.update o.key => o.value}
>
> -a

Oooh, Spiffy (tm) ;P Wish I thought of that. Possibly less efficient
though generating a lot of single-pair hashes that are instant garbage,
although it's all fun and games until someone runs a benchmark.

David Vallner


Ross Bamford

1/11/2006 9:23:00 AM

0

On Wed, 11 Jan 2006 04:31:52 -0000, Will <wrbriggs@gmail.com> wrote:

> Hi folks, I know that this is a really simple question, and there must
> be many ways to do it in Ruby... but what I'm looking for is an
> elegant way to take a collection of objects and create a hash mapping
> one attribute of the object as the key and the other as the value. So
> far what I am doing is this:
>
> objects = some_method_to_return_collect( method_params )
> myHash = Hash.new
>
> @objects.each do |object|
> myHash[ object.key ] = object.value
> end
>
> I played around with doing something like:
>
> @myHash = objects.map do |object| [ object.key => object.value ] end
>
> But that returns an array of single-value hashes, which is not exactly
> what I am trying to do.
>
> I know this is a stupid question, and probably pointless because I do
> know ways to do it, but I would really like the know the Ruby Way to do
> this. Ruby seems so given to elegant code that my code above really
> bugs me for some reason.
>

Stupid questions (i.e. the asking of) are my speciality these days ( :( )
and this doesn't seem to be a particularly dumb one to me :) You are
right though about a more elegant way to do it:

h = Hash['blue', 34, 'red', 31, 'green', 32] # => {"green"=>32,
"blue"=>34, "red"=>31}

a = [1, 'one', 2, 'two', 3, 'three'] # => [1, "one", 2, "two", 3,
"three"]
h = Hash[*a] # => {1=>"one", 2=>"two", 3=>"three"}

(Notice the * on the second form)

Cheers,

--
Ross Bamford - rosco@roscopeco.remove.co.uk

Ross Bamford

1/11/2006 9:51:00 AM

0

On Wed, 11 Jan 2006 09:23:04 -0000, Ross Bamford
<rosco@roscopeco.remove.co.uk> wrote:

> On Wed, 11 Jan 2006 04:31:52 -0000, Will <wrbriggs@gmail.com> wrote:
>
>> Hi folks, I know that this is a really simple question, and there must
>> be many ways to do it in Ruby... but what I'm looking for is an
>> elegant way to take a collection of objects and create a hash mapping
>> one attribute of the object as the key and the other as the value. So
>> far what I am doing is this:
>>
>> objects = some_method_to_return_collect( method_params )
>> myHash = Hash.new
>>
>> @objects.each do |object|
>> myHash[ object.key ] = object.value
>> end
>>
>> I played around with doing something like:
>>
>> @myHash = objects.map do |object| [ object.key => object.value ] end
>>
>> But that returns an array of single-value hashes, which is not exactly
>> what I am trying to do.
>>
>> I know this is a stupid question, and probably pointless because I do
>> know ways to do it, but I would really like the know the Ruby Way to do
>> this. Ruby seems so given to elegant code that my code above really
>> bugs me for some reason.
>>
>
> Stupid questions (i.e. the asking of) are my speciality these days
> ( :( ) and this doesn't seem to be a particularly dumb one to me :) You
> are right though about a more elegant way to do it:
>

Stupid answers, too. Seems I misread the question, sorry about that :(

(Sorry everyone for all this noise lately, I promise I'm going to start
enforcing a fifteen minute gap between writing and posting to try and make
sure I'm not just spouting crap again).

--
Ross Bamford - rosco@roscopeco.remove.co.uk

David Vallner

1/11/2006 3:29:00 PM

0

gwtmp01@mac.com wrote:

>
> Is this because the Smalltalk compiler will notice that there are no
> references to variables outside the block and Ruby's current
> implementation
> will not notice the same thing?
>
>
> Gary Wright
>
Quite so, Smalltalk compilers could optimize blocks that obviously
didn't close upon the lexical environment by dropping part or all of the
lexical binding. There was a thread about procs being a potential memory
leak on the list that discussed this in Ruby, you might want to look at
the ML archives.

One of the arguments raised in the thread was that this optimization
isn't really in Ruby because of eval. When blocks are called, they have
to be (usually) executed in the lexical scope in which they were
defined. The same is true of eval. Unfortunately, it's harder to
determine what in the surrounding scope is referenced in an eval call
than in a block, since the code is parsed at runtime; also you can't
really determine when eval is called because of aliasing. Therefore
optimizing the blocks would very likely break the use of eval in them.

I don't know what conclusion the original discussion came to, I'd
personally like to see eval mildly deprecated in favor of the many
other, more explicit, and cleaner reflection capacities like #class_eval
and #define_method for code generation, discouraged for use in the
standard library, and optimizing the blocks as optional interpreter / VM.

David Vallner


Ryan Leavengood

1/11/2006 7:41:00 PM

0

On 1/10/06, Will <wrbriggs@gmail.com> wrote:
>
> @myHash = objects.map do |object| [ object.key => object.value ] end

You were on the right track with this one:

@myHash = Hash[*objects.map{|o| [o.key, o.value]}.flatten]

So we map the objects into array pairs of the key and value, flatten
the resulting array, and then use the "splat" operator (*) to turn
those into parameters to the Hash::[] method.

Ryan