对象为JSON,列为键

时间:2015-04-23 22:07:35

标签: ruby-on-rails ruby json

我有一个Rate对象,其中包含date,rate和iso_code列。 我想要一个像这样的输出:

if

但如果我像这样渲染json:

{
EUR: {
  date: "2015-04-23",
  rate: 1.0772,
  btc_rate: 249.824
 },
....
}

我只有:

Rate.all.map { |r| {r.iso_code => {date: r.date, rate: r.rate, btc_rate: r.btc_rate}} }

每个对象都是哈希值。

1 个答案:

答案 0 :(得分:2)

您可以这样做:

Hash[Rate.all.map{|r| [r.iso_code, {date: r.date, rate: r.rate, btc_rate: r.btc_rate}]}]

这分为两部分:

  1. Rate.all.map创建一个包含2个元素数组的数组。在每个小数组中,我们希望第一个元素是键,第二个元素是结果哈希值。
  2. Hash[......]将上一步中的数组转换为我们想要的哈希值。
  3. 顺便说一下,我刚刚了解到在ruby 2.0中你可以使用array.to_h作为Hash[array]的更好看的替代品。

    或者你可以尝试更多的东西"命令式的风格":

    h = {}
    Rate.all.each do |r|
      h[r.iso_code] = {date: r.date, rate: r.rate, btc_rate: r.btc_rate}
    end
    

    或者您可以使用#inject简化(或复杂,取决于您的观点)上述方法:

    Rate.all.inject({}) do |h, r|
      h[r.iso_code] = {date: r.date, rate: r.rate, btc_rate: r.btc_rate}
      h
    end
    

    (顺便说一下,在所有这些中,我假设每个速率都有不同的iso_code。如果任何速率共享一个iso_code,只有最后一个将出现在结果散列中。)

    我推测第一种方法的效率会比另外两种方法效率低一些,因为它会分配所有这些后来必须进行垃圾回收的数组。