如何使用json作为嵌套哈希数组?

时间:2015-03-06 17:16:14

标签: ruby-on-rails ruby json

我的数据如下:

[
  {date: '2014/10/01', group: 'a', node: '2'},
  {date: '2014/10/01', group: 'b', node: '3'},
  {date: '2014/10/02', group: 'a', node: '4'},
  {date: '2014/10/02', group: 'b', node: '1'}
]

我将如何按照日期进行首次分组:

.group_by{|x| [x.date.strftime("%Y-%m-%d")}

然后由group然后node并将其渲染为嵌套的json?

我正在寻找类似的东西:

[
  {'2014/10/01': {groups: [{a: ['2'], b: ['3']}]},
  {'2014/10/02': {groups: [{a: ['4'], b: ['1']}]},
]

2 个答案:

答案 0 :(得分:4)

试试这个:

arr = [
  {date: '2014/10/01', group: 'a', node: '2'},
  {date: '2014/10/01', group: 'b', node: '3'},
  {date: '2014/10/02', group: 'a', node: '4'},
  {date: '2014/10/02', group: 'b', node: '1'}
]

arr.group_by { |item| item[:date] }.map do |k,v|
  Hash[k, { groups: v.map { |g| Hash[g[:group], [g[:node]]] }}]
end
#  => [{"2014/10/01"=>{:groups=>[{"a"=>["2"]}, {"b"=>["3"]}]}}, {"2014/10/02"=>{:groups=>[{"a"=>["4"]}, {"b"=>["1"]}]}}] 

答案 1 :(得分:1)

当遇到像这样的问题,涉及对数据的多次转换时,我经常发现将问题分成两个步骤是有用的,第一步是创建包含所有基本信息的数组或哈希;第二种是以所需的形式格式化数据。

最好描述一个例子的程序。问题中给出的那个很好:

arr = [
  {date: '2014/10/01', group: 'a', node: '2'},
  {date: '2014/10/01', group: 'b', node: '3'},
  {date: '2014/10/02', group: 'a', node: '4'},
  {date: '2014/10/02', group: 'b', node: '1'}
]

由于我们将在日期进行分组,因此将arr中的数据提取到密钥为日期的哈希中是有意义的。这些键的值是包含与:group的每个元素中:nodearr的值对应的键值对的哈希。我选择使用Hash#update(aka merge!)的形式来执行此操作,该形式使用块来确定合并的两个哈希中存在的键的值:

h = arr.each_with_object({}) { |g,h|
  h.update(g[:date]=>{ g[:group]=>g[:node] }) { |_,oh,nh|oh.update(nh) } }
  #=> {"2014/10/01"=>{"a"=>"2", "b"=>"3"},
  #    "2014/10/02"=>{"a"=>"4", "b"=>"1"}}

在继续格式化步骤之前,我应该指出,根据需求,在后续计算中使用此哈希可能更方便,而不是请求的数组。

使用Enumerable#map

,格式化现在非常简单
h.map { |d,g| { d=>{groups: [g] } } }
  #=> [{"2014/10/01"=>{:groups=>[{"a"=>"2", "b"=>"3"}]}},
  #    {"2014/10/02"=>{:groups=>[{"a"=>"4", "b"=>"1"}]}}]