tags:

views:

81

answers:

3

I have an array of hashes, and the values are all float numbers.

What are some good ways in Ruby to convert them all to int?

I have this way right now but wonder what other methods there are that are more elegant or clear:

analytics.map {|e| e.keys.each {|k| e[k] = e[k].to_i}; e}

Update: this is a run of the code:

> @analytics = [{:a => 1.1, :b => 123.456}, {'c' => 765.432}]
 => [{:a=>1.1, :b=>123.456}, {"c"=>765.432}] 

> @analytics.map {|e| e.keys.each {|k| e[k] = e[k].to_i}; e} 
 => [{:a=>1, :b=>123}, {"c"=>765}] 

> @analytics
 => [{:a=>1, :b=>123}, {"c"=>765}]
+4  A: 
analytics.map {|h| Hash[h.map {|k, v| [k, v.to_i] }] }

Looks kind of neat.

In general, whenever I find myself juggling several nested iterators, I try to refactor my object model such that I'm actually dealing with actual objects, not just a twisted maze of nested arrays and hashes. This seems to be right on the fence.

After all, Ruby is an object-oriented programming language, not a hash-oriented one.

Jörg W Mittag
I've wondered if a hash of hash (of hash of hash of ...) is a code smell. What approach do you take? Do you replace `hash[key1][key2][key3]` with `hash[actual_object]`, where `actual_object` has `key1`, `key2` and `key3` in it?
Andrew Grimm
@Andrew Grimm: Something like that. It's hard to say in this case, since `:a`, `:b` and `'c'` aren't exactly descriptive names. If I write quick one-off scripts, I often tend to do the whole hash thing myself. I just got an iPod, and thus wrote a small script to convert my music collection from FLAC to MP3, keeping all metadata intact. I slurped all data into a big fat hash, then iterated over it, converting the files one by one. Debugging consisted mostly of making YAML dumps of the hash and staring at it, trying to figure out which loop is how many levels deep in which array.
Jörg W Mittag
Jörg W Mittag
+1  A: 

In place:

a = [{:a=>1.1, :b=>2.1},{:a=>3.0, :b=>4.1}]
a.each {|h| h.each_pair {|k,v| h[k] = v.to_i}}
p a
# => [{:a=>1, :b=>2}, {:a=>3, :b=>4}]
steenslag
+1  A: 

This is a solution with FP style (no in-place modifications) that uses the handy Enumerate#mash from Facets:

analytics.map { |h| h.mash { |key, value| [key, value.to_i] } }

Enumerable#mash is a map+to_hash. See more info here.

tokland