用Ruby遍历哈希表中的每个键值对

17

我在使用MongoDB的时候遇到了一些问题,它总是返回带有双引号键和整数作为浮点数的哈希值。这个问题有没有困扰过其他人呢?

例如,在进行map reduce或分组操作之后,我得到了一堆像这样的哈希值:

{"unknown"=>54.0, "pedestrians"=>572.0, "vehicles"=>1045.0}

但是我真正想要的是:

{ unknown: 54, pedestrians: 572, vehicles: 1045 }

有什么简单的方法可以帮我进行转换吗?


这个能帮上你吗?请查看 symbolize_keys:http://as.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/Keys.html#M000244 - VNO
2个回答

35

你可以这样做:

original = {"unknown"=>54.0, "pedestrians"=>572.0, "vehicles"=>1045.0}
converted = Hash[ original.map { |key, value| [key.to_sym, value.to_i] } ]

如果你在使用Rails,你可以把它变成一个HashWithIndifferentAccess,并且只需要转换值:

original = HashWithIndifferentAccess.new(original)
original.each { |key, value| original[key] = value.to_i }

如果值是字符串或者实际上有小数怎么办? - DigitalRoss
@DigitalRoss 嗯,这个答案假设原始哈希总是 String => Float。如果类型是其他的话,它就不起作用 - 但这不是问题所在。 - Russell
@TylerBrock 谢谢!虽然我编辑掉了使用“tap”的版本,因为我认为只使用“map”并转换回“Hash”更整洁。 - Russell

3

信任完整FP值

为了正确处理所有可能的键类型,如果你要进行转换,我建议这样操作:

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)

上述代码将把哈希表中实际为整数的Float值转换为Integer。
但实际上你完全不需要这样做。虽然不信任浮点格式很常见,但事实证明它们确实准确地表示整数值。
你可以相信数据库中的任何整数值都会与整数常量(包括0)进行精确比较,而且你 不会 看到任何舍入的副作用。
当然,如果你将一个浮点数除以其他因子,你 注意到差异。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接