Reputation: 48535
I have a bit of a problem with MongoDB in that it returns hashes with the keys in double quotes and integers as floats all the time, has this been a problem for anyone else?
for examples after a map reducing or grouping, say I have a bunch of hashes which look like this:
{"unknown"=>54.0, "pedestrians"=>572.0, "vehicles"=>1045.0}
But what I really want is:
{ unknown: 54, pedestrians: 572, vehicles: 1045 }
Any ideas on how I can easily convert it?
Upvotes: 18
Views: 66391
Reputation: 146151
In order to handle all possible key types correctly, if you are going to convert it I would suggest something like:
h = {:a => 54.0, :b => 572.0, :c => 1045.0, :d => 'test', :e => 1.23 }
p(h.merge(h) do |k, v|
v = v.to_i if v.is_a?(Float) && v.to_i == v
v
end)
The above code will convert Float values in a hash that are actually integral to Integer.
But you actually don't need to do this at all. While it's common to distrust the floating point formats, it turns out that they do represent integral values exactly.
You can trust that any value that was an integer in the database will compare exactly with integer constants (including 0) and that you will not see any rounding artifacts.
You will notice a difference, of course, if you divide a float by something other than a factor.
Upvotes: 3
Reputation: 12439
You could do:
original = {"unknown"=>54.0, "pedestrians"=>572.0, "vehicles"=>1045.0}
converted = Hash[ original.map { |key, value| [key.to_sym, value.to_i] } ]
Or if you're using Rails, you could make it a HashWithIndifferentAccess
and just convert the values:
original = HashWithIndifferentAccess.new(original)
original.each { |key, value| original[key] = value.to_i }
Upvotes: 36