# Data sctructure

**URL:** <https://www.ruby-forum.com/t/data-sctructure/174540>\
**Category:** Ruby\
**Created:** [August 28, 2009, 12:25pm UTC](https://www.ruby-forum.com/t/data-sctructure/174540 "2009-08-28T12:25:05Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Juliano\_SSS\_SSSS\_SS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/77aa72/32.png) [@Juliano\_SSS\_SSSS\_SS](https://www.ruby-forum.com/u/Juliano_SSS_SSSS_SS)\
**Post date:** [August 28, 2009, 12:25pm UTC](https://www.ruby-forum.com/t/data-sctructure/174540/1 "2009-08-28T12:25:05Z")

</div>

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! 🙂

---

<div class="post-metadata">

**Author:** ![Juliano\_SSS\_SSSS\_SS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/77aa72/32.png) [@Juliano\_SSS\_SSSS\_SS](https://www.ruby-forum.com/u/Juliano_SSS_SSSS_SS)\
**Post date:** [August 28, 2009, 1:02pm UTC](https://www.ruby-forum.com/t/data-sctructure/174540/2 "2009-08-28T13:02:33Z")

</div>

2009/8/28 David A. Black [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

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

---

<div class="post-metadata">

**Author:** ![Juliano\_SSS\_SSSS\_SS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/77aa72/32.png) [@Juliano\_SSS\_SSSS\_SS](https://www.ruby-forum.com/u/Juliano_SSS_SSSS_SS)\
**Post date:** [August 28, 2009, 12:43pm UTC](https://www.ruby-forum.com/t/data-sctructure/174540/3 "2009-08-28T12:43:49Z")

</div>

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](http://www.rubypal.com)

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

---

<div class="post-metadata">

**Author:** ![Juliano\_SSS\_SSSS\_SS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/77aa72/32.png) [@Juliano\_SSS\_SSSS\_SS](https://www.ruby-forum.com/u/Juliano_SSS_SSSS_SS)\
**Post date:** [August 28, 2009, 1:16pm UTC](https://www.ruby-forum.com/t/data-sctructure/174540/4 "2009-08-28T13:16:01Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Juliano\_SSS\_SSSS\_SS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/77aa72/32.png) [@Juliano\_SSS\_SSSS\_SS](https://www.ruby-forum.com/u/Juliano_SSS_SSSS_SS)\
**Post date:** [August 28, 2009, 1:20pm UTC](https://www.ruby-forum.com/t/data-sctructure/174540/5 "2009-08-28T13:20:42Z")

</div>

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
```
