如何在Ruby for Highcharts中将多键哈希转换为单键哈希

时间:2016-09-17 08:34:33

标签: ruby-on-rails json ruby ruby-on-rails-4 highcharts

我在Ruby中有这些数据,用于创建使用Highcharts.js的条形图,这需要JSON格式的数据:

data = {["January", "a"]=>54, ["January", "b"]=>13, ["January", "d"]=>2, ["January", "c"]=>1, 
        ["February", "a"]=>27, ["February", "b"]=>11, ["February", "c"]=>4, ["March", "a"]=>22, 
        ["March", "b"]=>11, ["March", "d"]=>2, ["March", "c"]=>2, ["April", "a"]=>32, 
        ["April", "b"]=>12, ["April", "d"]=>6, ["April", "c"]=>2, ["May", "a"]=>7, 
        ["May", "d"]=>3, ["June", "a"]=>5, ["July", "a"]=>25, 
        ["August", "a"]=>23, ["August", "d"]=>3, ["August", "c"]=>3, ["September", "a"]=>6}

数据存储在变量中,而不是来自文件。

我想将其转换为json对象,以将其发送到Highcharts进行制图。我需要以下格式的数据:

category = ["January","February","March","April","May","June","July","August","September"]

series: [{
            name: 'a',
            data: [54, 27, 22, 32, 7, 5, 25, 23, 6]
        }, {
            name: 'b',
            data: [13, 11, 11, 12, 6, 0, 0, 0, 6]
        }, {
            name: 'c',
            data: [1, 4, 0, 2, 0, 0, 0, 3, 6]
        },
            {
            name: 'd',
            data: [2, 0, 0, 6, 3, 0, 0, 3, 6]
        }]

数据缺失了几个月,有时不按字母顺序排列。

Ruby中是否有一种简单的方法可以取消原始Hash的列表,然后在用0填充缺失值的同时从中提取信息,并根据需要获取JSON输出?

P.S。 :尝试转换data.to_json但highcharts不接受原始形式。有没有其他方法可以在Highcharts中使用这些数据创建条形图?

3 个答案:

答案 0 :(得分:1)

您可以尝试使用lazy_high_charts gem在我们的Controller中渲染HighCharts。

因此可以轻松自定义图表的数据。

答案 1 :(得分:0)

我不确定应该在系列数据数组中插入这些零的逻辑,但这可能会让你几乎在那里:

def transform(data)
  hash = { :category => [], :series => [] }

  data.keys().reduce(hash) { |accum, key|
    month = key[0]
    letter = key[1]

    # Push month
    accum[:category].push(month) if !accum[:category].include?(month)

    # Find existing item in series or create new one
    existing = accum[:series].select { |item| item[:name] == letter }
    item = existing.length > 0 ? existing[0] : {:name => letter, :data => []}

    # Push the number value in item's data
    item[:data].push(data[key])

    # Collect item if not already in series array
    accum[:series].push(item) if existing.length == 0

    accum
  }
end

result = transform(MY_DATA_HERE)
result[:series].sort! {|a,b| a[:name] <=> b[:name] } # sort them!

puts result

输出:

{
  :category=>["January", "February", "March", "April", "May", "June", "July", "August", "September"], 
  :series=>[
    {:name=>"a", :data=>[54, 27, 22, 32, 7, 5, 25, 23, 6]}, 
    {:name=>"b", :data=>[13, 11, 11, 12]}, 
    {:name=>"c", :data=>[1, 4, 2, 2, 3]}, 
    {:name=>"d", :data=>[2, 2, 6, 3, 3]}
  ]
}

答案 2 :(得分:0)

catser = data.each_with_object(category: [], series: {}) do |(k, v), memo|
  memo[:category] << k.first
  (memo[:series][k.last] ||= []) << v
end
category, series = [
  catser[:category].uniq.sort,
  catser[:series].map { |k, v| { name: k, data: v } }
]