繁体   English   中英

将以数组作为键的红宝石哈希值转换为以单个值作为键的值的最有效方法

[英]Most efficient way to convert a ruby hash with array as keys to one with single values as keys

我坚持重新安排红宝石哈希的最佳方法是什么。

主要目标是按月和计数对mysql的结果进行分组。

为此,我提出了以下要求:

@data = Model.find(params[:id])
             .jobs
             .group('year(created_at)')
             .group('month(created_at)')
             .count(:id)

这给了我:

#=> {[2013, 12]=>9, [2014, 1]=>4, [2014, 3]=>3, 
#    [2014, 4]=>1, [2014, 6]=>1, [2014, 7]=>1, [2014, 10]=>2}

我正在尝试使用更整洁的哈希或数组来转换为JSON,其中年份不重复。

我该如何使用类似{"Year" => [Month,Count value]} (或其他形式)

理念? (我运行ruby 2.2)

@mudosobwa提出的答案可能是正确的,但是由于目标是json文件,因此您可能需要一些“命名”键。 我建议你这个:

formated_results = @data.group_by{|k, v| k[0]}.collect{|k,v| {year: k, datas: v.collect{|vv| {month: vv.first.last, count: vv.last}}}}
# {:year=>2013, :datas=>[{:month=>12, :count=>9}]}
# {:year=>2014, :datas=>[{:month=>1, :count=>4}, {:month=>3, :count=>3}, {:month=>4, :count=>1}, {:month=>6, :count=>1}, {:month=>7, :count=>1}, {:month=>10, :count=>2}]}

编辑 :没有group_by方法的另一个解决方案:

formated_results = Hash.new{|h,k| h[k] = []}
@data.each{|k,v| formated_results[k[0]] << {month: k[1], count: v}}
formated_results = formated_results.collect{|k, v| {year: k, datas: v}}
# {:year=>2013, :datas=>[{:month=>12, :count=>9}]}
# {:year=>2014, :datas=>[{:month=>1, :count=>4}, {:month=>3, :count=>3}, {:month=>4, :count=>1}, {:month=>6, :count=>1}, {:month=>7, :count=>1}, {:month=>10, :count=>2}]}

那你只需要

formated_results.to_json

json结果应为:

[
  {
    "year": 2013,
    "datas": [
      { "month": 12, "count": 9 }
    ]
  },
  {
    "year": 2014,
    "datas": [
      { "month": 1, "count": 4 },
      { "month": 3, "count": 3 },
      { "month": 4, "count": 1 },
      { "month": 6, "count": 1 },
      { "month": 7, "count": 1 },
      { "month": 10, "count": 2 }
    ]
  }
]

假设您已经在@data哈希,则可以:

@data.inject({}) do |memo, ((y, m), cnt)| 
  (memo[y] ||= {})[m] =  cnt
  memo
end
#⇒ { 
#    2013 => {12 => 9}, 
#    2014 => {1 => 4, 10 => 2, 3 => 3, 4 => 1, 6 => 1, 7 => 1}
#  }

正如@Surya在评论中指出的那样,它应该是哈希Year => Hash[Month, Count] 当您仍然希望拥有Month, Count数组时Month, Count

@data.inject({}) do |memo, ((y, m), cnt)| 
  memo[y] ||= []
  memo[y] << [m,  cnt]
  memo
end

到json:

require 'json'
result.to_json
#=> "{\"2013\":{\"12\":9},\"2014\":{\"1\":4,\"3\":3,\"4\":1,\"6\":1,\"7\":1,\"10\":2}}"
@data.to_a.group_by{|ym, c| ym.first }.map{|year, months| [year,months.map{|m,cnt| [m.last, cnt] }] }.to_h
=> {2013=>[[12, 9]], 2014=>[[1, 4], [3, 3], [4, 1], [6, 1], [7, 1], [10, 2]]}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM