[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

database row in a hash

Raphael Bauduin

10/29/2003 9:53:00 AM

Hi,

I'm working woth the ruby postgresql interface. Due to my previous use
of other languages, I am used to have access to a retrieved row in the
form of a Hash( "field" => field_name, value => cell_value) .

Now I write this in ruby:

res.result.each do |tupl|
tupl.each do |fld|
puts "#{res.fields[tupl.index(fld)]} = #{fld}"
end
end

while I'm used to write something like this:

res.result.each_hash do |tupl|
tupl.each_pair do |fld, value|
puts "#{field} = #{value}
end
end


I'm not pretending the second solution is best... (hashes don't ensure
order)

It's just I found this functionality very handy in some cases and it
brought me to a question:
what's the easiest way to build that hash for a row? I have the keys in
res.fields, and the values in tupl. With that info, can I directly build
the hash, with a constructor like row_hash=Hash.new(res.fields, tupl) ?

Thanks.

Raph

8 Answers

Robert Klemme

10/29/2003 4:15:00 PM

0


"Raphael Bauduin" <raphael.bauduin@be.easynet.net> schrieb im Newsbeitrag
news:3f9f8e2d$0$1120$6c56d894@feed0.news.be.easynet.net...
> Hi,
>
> I'm working woth the ruby postgresql interface. Due to my previous use
> of other languages, I am used to have access to a retrieved row in the
> form of a Hash( "field" => field_name, value => cell_value) .
>
> Now I write this in ruby:
>
> res.result.each do |tupl|
> tupl.each do |fld|
> puts "#{res.fields[tupl.index(fld)]} = #{fld}"
> end
> end
>
> while I'm used to write something like this:
>
> res.result.each_hash do |tupl|
> tupl.each_pair do |fld, value|
> puts "#{field} = #{value}
> end
> end
>
>
> I'm not pretending the second solution is best... (hashes don't ensure
> order)
>
> It's just I found this functionality very handy in some cases and it
> brought me to a question:
> what's the easiest way to build that hash for a row? I have the keys in
> res.fields, and the values in tupl. With that info, can I directly build
> the hash, with a constructor like row_hash=Hash.new(res.fields, tupl) ?

You could do res.fields.zip( tupl ) which yields a nested array:

irb(main):034:0> ["name","age"].zip(["john",20])
=> [["name", "john"], ["age", 20]]

Apparently there's no std way to turn this into a hash, but you could
define:

module Enumerable
def to_hash
h={}
each do |k,v|
h[k]=v
end
h
end
end

Then:

irb(main):033:0> ["name","age"].zip(["john",20]).to_hash
=> {"name"=>"john", "age"=>20}

or in your case

h = res.fields.zip(tupl).to_hash

Regards

robert

Simon Strandgaard

10/29/2003 6:08:00 PM

0

On Wed, 29 Oct 2003 17:14:40 +0100, Robert Klemme wrote:
[snip]
> module Enumerable
> def to_hash
> h={}
> each do |k,v|
> h[k]=v
> end
> h
> end
> end
>
> Then:
>
> irb(main):033:0> ["name","age"].zip(["john",20]).to_hash
> => {"name"=>"john", "age"=>20}
>

Why are #inject not splitting the pair into k and v ?

irb(main):011:0> x=[["name", "john"], ["age", 20]]
=> [["name", "john"], ["age", 20]]
irb(main):012:0> x.inject({}){|h,k,v|h[k]=v;h}
=> {["name", "john"]=>nil, ["age", 20]=>nil}
irb(main):013:0>

Should'nt #inject do that ?

--
Simon Strandgaard


Simon Strandgaard

10/29/2003 6:40:00 PM

0

On Wed, 29 Oct 2003 19:07:38 +0100, Simon Strandgaard wrote:

> On Wed, 29 Oct 2003 17:14:40 +0100, Robert Klemme wrote:
> [snip]
>> module Enumerable
>> def to_hash
>> h={}
>> each do |k,v|
>> h[k]=v
>> end
>> h
>> end
>> end
>>
>> Then:
>>
>> irb(main):033:0> ["name","age"].zip(["john",20]).to_hash
>> => {"name"=>"john", "age"=>20}
>>
>
> Why are #inject not splitting the pair into k and v ?
>
> irb(main):011:0> x=[["name", "john"], ["age", 20]]
> => [["name", "john"], ["age", 20]]
> irb(main):012:0> x.inject({}){|h,k,v|h[k]=v;h}
> => {["name", "john"]=>nil, ["age", 20]=>nil}
> irb(main):013:0>
>
> Should'nt #inject do that ?


I whish something like this:

module Enumerable
def foldr(n, &block)
if block.arity == 2
each{|v|n=block.call(n,v)}
else
each{|v|n=block.call(n,*v)}
end
n
end
end

x=[["name", "john"], ["age", 20]]
p x.foldr({}){|h,k,v|h[k]=v;h}
#=> {"name"=>"john", "age"=>20}


Perhaps I should submit a RCR for changing #inject into the above #foldr ?

--
Simon Strandgaard





Florian Gross

10/29/2003 8:05:00 PM

0

Moin!

Robert Klemme wrote:

> You could do res.fields.zip( tupl ) which yields a nested array:
>
> irb(main):034:0> ["name","age"].zip(["john",20])
> => [["name", "john"], ["age", 20]]
>
> Apparently there's no std way to turn this into a hash

There is, but it's a bit obscure:

arr = ["name","age"].zip(["john",20])
Hash[*arr.flatten] # => {"name"=>"john", "age"=>20}

> Regards
> robert

More regards,
Florian Gross



Robert Klemme

10/30/2003 8:36:00 AM

0


"Simon Strandgaard" <qj5nd7l02@sneakemail.com> schrieb im Newsbeitrag
news:pan.2003.10.29.18.07.38.655881@sneakemail.com...
> On Wed, 29 Oct 2003 17:14:40 +0100, Robert Klemme wrote:
> [snip]
> > module Enumerable
> > def to_hash
> > h={}
> > each do |k,v|
> > h[k]=v
> > end
> > h
> > end
> > end
> >
> > Then:
> >
> > irb(main):033:0> ["name","age"].zip(["john",20]).to_hash
> > => {"name"=>"john", "age"=>20}
> >
>
> Why are #inject not splitting the pair into k and v ?
>
> irb(main):011:0> x=[["name", "john"], ["age", 20]]
> => [["name", "john"], ["age", 20]]
> irb(main):012:0> x.inject({}){|h,k,v|h[k]=v;h}
> => {["name", "john"]=>nil, ["age", 20]=>nil}
> irb(main):013:0>
>
> Should'nt #inject do that ?

Thanks for that great idea! You can do it this way:

irb(main):001:0>
["name","age"].zip(["john",20]).inject({}){|h,kv|h[kv[0]]=kv[1];h}
=> {"name"=>"john", "age"=>20}
irb(main):002:0>

Regards

robert

Robert Klemme

10/30/2003 8:41:00 AM

0


"Simon Strandgaard" <qj5nd7l02@sneakemail.com> schrieb im Newsbeitrag
news:pan.2003.10.29.18.40.10.757877@sneakemail.com...
> On Wed, 29 Oct 2003 19:07:38 +0100, Simon Strandgaard wrote:
>
> > On Wed, 29 Oct 2003 17:14:40 +0100, Robert Klemme wrote:
> > [snip]
> >> module Enumerable
> >> def to_hash
> >> h={}
> >> each do |k,v|
> >> h[k]=v
> >> end
> >> h
> >> end
> >> end
> >>
> >> Then:
> >>
> >> irb(main):033:0> ["name","age"].zip(["john",20]).to_hash
> >> => {"name"=>"john", "age"=>20}
> >>
> >
> > Why are #inject not splitting the pair into k and v ?
> >
> > irb(main):011:0> x=[["name", "john"], ["age", 20]]
> > => [["name", "john"], ["age", 20]]
> > irb(main):012:0> x.inject({}){|h,k,v|h[k]=v;h}
> > => {["name", "john"]=>nil, ["age", 20]=>nil}
> > irb(main):013:0>
> >
> > Should'nt #inject do that ?
>
>
> I whish something like this:
>
> module Enumerable
> def foldr(n, &block)
> if block.arity == 2
> each{|v|n=block.call(n,v)}
> else
> each{|v|n=block.call(n,*v)}
> end
> n
> end
> end
>
> x=[["name", "john"], ["age", 20]]
> p x.foldr({}){|h,k,v|h[k]=v;h}
> #=> {"name"=>"john", "age"=>20}

This is not nice:

irb(main):015:0> {1=>2,3=>4}.foldr({}){|a,b| p [a,b]}
(irb):5: warning: multiple values for a block parameter (2 for 1)
from (irb):5
[{}, [1, 2]]
(irb):5: warning: multiple values for a block parameter (2 for 1)
from (irb):5
[nil, [3, 4]]
=> nil
irb(main):016:0>

> Perhaps I should submit a RCR for changing #inject into the above #foldr
?

I would not do that. It does not feel right. The fact, that the constant
2 appears in the implementation smells like too much specialization IMHO.
Better sleep one more night about this... :-)

Kind regards

robert


Raphael Bauduin

10/30/2003 12:40:00 PM

0

Raphael Bauduin wrote:
> Hi,
>
> I'm working woth the ruby postgresql interface. Due to my previous use
> of other languages, I am used to have access to a retrieved row in the
> form of a Hash( "field" => field_name, value => cell_value) .
>
> Now I write this in ruby:
>
> res.result.each do |tupl|
> tupl.each do |fld|
> puts "#{res.fields[tupl.index(fld)]} = #{fld}"
> end
> end
>


Btw, this code isn't working if you have 2 columns in one row containing
the same value....

Thanks for all solutions to my question :-)

Raph


> while I'm used to write something like this:
>
> res.result.each_hash do |tupl|
> tupl.each_pair do |fld, value|
> puts "#{field} = #{value}
> end
> end
>
>
> I'm not pretending the second solution is best... (hashes don't ensure
> order)
>
> It's just I found this functionality very handy in some cases and it
> brought me to a question:
> what's the easiest way to build that hash for a row? I have the keys in
> res.fields, and the values in tupl. With that info, can I directly build
> the hash, with a constructor like row_hash=Hash.new(res.fields, tupl) ?
>
> Thanks.
>
> Raph
>

Robert Klemme

10/30/2003 2:38:00 PM

0


"Raphael Bauduin" <raphael.bauduin@be.easynet.net> schrieb im Newsbeitrag
news:3fa106c2$0$1128$6c56d894@feed0.news.be.easynet.net...
> Raphael Bauduin wrote:
> > Hi,
> >
> > I'm working woth the ruby postgresql interface. Due to my previous use
> > of other languages, I am used to have access to a retrieved row in the
> > form of a Hash( "field" => field_name, value => cell_value) .
> >
> > Now I write this in ruby:
> >
> > res.result.each do |tupl|
> > tupl.each do |fld|
> > puts "#{res.fields[tupl.index(fld)]} = #{fld}"
> > end
> > end
> >
>
>
> Btw, this code isn't working if you have 2 columns in one row containing
> the same value....

You'd rather want to do:

res.result.each do |tupl|
tupl.each_with_index do |fld,idx|
puts "#{res.fields[idx]} = #{fld}"
end
end

> Thanks for all solutions to my question :-)

You're welcome!

robert