Data sctructure

Hello guys.

I’ve just started using ruby and I come from Python… I’m still
learning to think the Ruby way…
Of course, any beginning is hard, but even so I’ve been having a lot
of fun learning Ruby.
The problem is that I still don’t know much about the tons of methods
and I’m maybe letting something pass through my fingers.

My problem is this:
I have to read a file and set up a data structure of embedded
dictionaries. In Python I can easily do that by means of
“dict.defaultdict()”, but I didn’t understand how to do that in
Ruby… I finally came up with the following:

def preprocess(lines)
d = {}
lines.each do |line|
c, s, fc, fl = line.split("\t")
if !d.has_key? c
d[c] = {}
end
if !d[c].has_key? s
d[c][s] = {}
end
if !d[c][s].has_key? fc
d[c][s][fc] = []
end
d[c][s][fc].push fl
end
return d
end

My question is: Is there an easier way to do this in Ruby as it is in
Python?

Same code in Python…

def preprocess(lines):
    d = {}
    for line in lines:
        c, s, fc, fl = line
        dc = d.setdefault(c, {})
        ds = dc.setdefault(s, {})
        dfc = ds.setdefault(fc, [])
        lfl = dfc.append(fl)
    return d

Thank you very much! :slight_smile:

2009/8/28 David A. Black [email protected]:

learning to think the Ruby way…
dictionaries. In Python I can easily do that by means of
if !d[c].has_key? s
My question is: Is there an easier way to do this in Ruby as it is in
d[c][s] ||= {}
There are also ways to set the default behavior of hashes, but I think
the above is probably the most direct way to do what you want.

You mean something like the more involved

def preprocess(lines)
d = Hash.new {|h,k| h[k] = Hash.new(&h.default_proc)}

lines.each do |line|
c, s, fc, fl = line.split(“\t”)
(d[c][s][fc] ||= []) << fl
end

d
end

Kind regards

robert

Hi –

On Fri, 28 Aug 2009, Juliano 준호 wrote:

Hello guys.

I’ve just started using ruby and I come from Python… I’m still
learning to think the Ruby way…
Of course, any beginning is hard, but even so I’ve been having a lot
of fun learning Ruby.

Welcome! I’m glad you’re enjoying it.

d = {}
end
d[c][s][fc].push fl
end
return d
end

My question is: Is there an easier way to do this in Ruby as it is in
Python?

The idiom for conditional assignment in Ruby is ||= (or-equals). You
could do this:

def preprocess(lines)
d = {}
lines.each do |line|
c, s, fc, fl = line.split(“\t”)
d[c] ||= {}
d[c][s] ||= {}
d[c][s][fc] ||= []
d[c][s][fc].push fl
end
return d
end

The only thing is, in cases where you want false or nil to be a hash
value, ||= will over-eagerly do the assignment. But that’s not the
case here.

There are also ways to set the default behavior of hashes, but I think
the above is probably the most direct way to do what you want.

David


David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com

September Ruby training in NJ has been POSTPONED. Stay tuned
for updates!

Hi –

On Fri, 28 Aug 2009, Robert K. wrote:

I’ve just started using ruby and I come from Python… I’m still
I have to read a file and set up a data structure of embedded
end

 d[c]        ||= {}
(d[c][s][fc] ||= []) << fl

end

d
end

Yes, that’s what I meant.

David

At 2009-08-28 06:16AM, “Juliano ??” wrote:

I have to read a file and set up a data structure of embedded
dictionaries. In Python I can easily do that by means of
“dict.defaultdict()”, but I didn’t understand how to do that in
Ruby… I finally came up with the following:

Referencing a hash element that doesn’t exist returns nil, so you might
be looking for the ||= operator:

a ||= b  # if a is false or nil, then set a=b, else return value of 

a

     if !d[c][s].has_key? fc
       d[c][s][fc] = []
     end
   d[c][s][fc].push fl
 end
 return d

end

def preprocess(lines)
  d = {}
  lines.each do |line|
    c,s,fc,fl = line.split("\t")
    d[c]        ||= {}
    d[c][s]     ||= {}
    d[c][s][fc] ||= []
    d[c][s][fc] << fl
  end
  d
end