From: Robert Klemme Date: 2009-08-28T19:57:43+09:00 Subject: Re: data sctructure 2009/8/28 David A. Black : > This message is in MIME format. The first part should be readable text, > while the remaining parts are likely unreadable without MIME-aware tools. > > 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. > >> 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? > > 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. 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 -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/