帮助转换数组和哈希

时间:2011-04-10 20:50:52

标签: ruby arrays hash

我正在尝试在我的网络应用程序中使用Highcharts,但是我在使我的数组与高图需要的输出相匹配时遇到了一些麻烦,本质上hightcharts需要输出这样的JS:

series: [{
   name: 'person',
   data: [1562, 873, 1457]
}, {
   name: 'car',
   data: [7323, 324, 1233]
}, {
   name: 'SUV',
   data: [832, 6232, 4432]
}]

在这种情况下数据数组中的每个项目都是新的一天,我的问题是我的数据组织方式有点不同,并且尝试转换我的数据以匹配这一点一直很令人头疼。基本上我的输出是这样的:

[
  {:date=>"Sun, 10 Apr 2011", :object_types=>[
    {:count=>4279, :class_name=>"person"}, 
    {:count=>8785, :class_name=>"car"}, 
    {:count=>2153, :class_name=>"SUV"}
  ]}, 
  {:date=>"Sat, 09 Apr 2011", :object_types=>[
    {:count=>12206, :class_name=>"person"}, 
    {:count=>29095, :class_name=>"car"}, 
    {:count=>7565, :class_name=>"SUV"}
  ]}, 
  {:date=>"Fri, 08 Apr 2011", :object_types=>[
    {:count=>4159, :class_name=>"person"}, 
    {:count=>8043, :class_name=>"car"}, 
    {:count=>1982, :class_name=>"SUV"}
  ]}
] 

所以我似乎需要首先按照(在我的情况下):class_name分组项目,然后在:count内按data中的每个项目分组。

我很难找到优雅地执行此操作的“红宝石方式”,我在操作阵列和散列方面并不是非常棒,你可能会看到,但是在指导我实现这一点时有任何帮助我很感激。


其次,我试图在我的查询中使用group()来完成此操作,但这似乎并没有帮助太多,想法?我要解决的另一件事是如果没有记录就填写“0”的日期......但是我认为下一步我会解决。

3 个答案:

答案 0 :(得分:1)

这样的事情应该有效:

def convert_data(input) 
  hash = {} 
  input.each do |o| 
    o[:object_types].each do |ot| 
      if hash[ot[:class_name]] 
        hash[ot[:class_name]] << ot[:count] 
      else 
        hash[ot[:class_name]] = [ot[:count]] 
      end 
    end 
  end 
  hash.map {|k,v| {'name' => k, 'data' => v}}
end

您可以使用输入数据调用此函数,并且您有一个符合您对Highcharts库所期望的格式的对象。

答案 1 :(得分:1)

aux = Hash.new(Array.new)
series = Array.new

# After this code the aux hash will look something like this: {:person => [4159, 1231, 255], :suv => [1231, 4123, 5411], :car => [321, 312, 541]}
raw_array.each do |date_hash|
  date_hash[:object_types].each do |inf|
    aux[inf[:class_name]] << inf[:count]
  end
end

aux.each { |k,v| series << {:name => k.to_s, :data => v} }

那个系列数组就是你需要的。就像json一样渲染它。

答案 2 :(得分:1)

我会使用Enumerable#group_by,因为那是更难的部分;其余的只是基本的转变:

r = data.flat_map{|h| h[:object_types]}.
  group_by{|h| h[:class_name]}.
  map do |class_name, hashes|
    {:name => class_name, :data => hashes.map{|h| h[:count]}}
  end

注意group_by位于ActiveRecord或Ruby 1.8.7+中。 flat_map是Ruby 1.9.2的新功能。使用正确的版本或require "backports"