database row in a hash

R

Raphael Bauduin

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
 
R

Robert Klemme

Raphael Bauduin said:
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
 
S

Simon Strandgaard

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 ?
 
S

Simon Strandgaard

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 ?
 
F

Florian Gross

Moin!

Robert said:
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
 
R

Robert Klemme

Simon Strandgaard said:
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
 
R

Robert Klemme

Simon Strandgaard said:
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
 
R

Raphael Bauduin

Raphael said:
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
 
R

Robert Klemme

Raphael Bauduin said:
Raphael said:
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
 

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
474,139
Messages
2,570,805
Members
47,351
Latest member
LolaD32479

Latest Threads

Top