【问题标题】:How to return an array of hashes grouped by a certain column如何返回按特定列分组的哈希数组
【发布时间】:2014-03-09 05:45:19
【问题描述】:

我有一个展示位置模型,可以在日志中显示员工及其月末职位:

[<Placement id: 1, employee_name: 'John', month: "2014-02-01",position: 2>, 
<Placement id: 2, employee_name: 'John', month: "2014-01-01", position: 2>, 
<Placement id: 3, employee_name: 'Jill', month: "2014-02-01", position: 3>,
<Placement id: 4, employee_name: 'Jill', month: "2014-01-01", position: 1>
<Placement id: 5, employee_name: 'Fred', month: "2014-02-01", position: 1>]

我将如何返回如下所示的哈希数组:

[
{ month: '2014-02-01', 'John': 2, 'Jill': 3, 'Fred': 1 },
{ month: '2014-01-01', 'John': 2, 'Jill': 1 }
]

【问题讨论】:

  • 返回这种类型的值可以使用jbulder
  • 这些不是有效的哈希值。
  • @thorstenmüller 但我打赌你明白 OP 的要求。
  • your_array.as_json 将起作用
  • @NitinJ 不,因为哈希与数组不同。

标签: ruby-on-rails ruby


【解决方案1】:
a = [ <Placement id: 1, employee_name: 'John', month: "2014-02-01",position: 2>, 
      <Placement id: 2, employee_name: 'John', month: "2014-01-01", position: 2>, 
      <Placement id: 3, employee_name: 'Jill', month: "2014-02-01", position: 3>,
      <Placement id: 4, employee_name: 'Jill', month: "2014-01-01", position: 1>
      <Placement id: 5, employee_name: 'Fred', month: "2014-02-01", position: 1> ]

a.group_by(&:month).map  do |month, data|
  hash = {month: month}
  data.each {|placement| hash[placement.employee_name] = placement.position}
  hash
end  

【讨论】:

    【解决方案2】:

    您可以使用 Activemodel 序列化程序as_json

    例如来自文档

    user = User.find(1)
    user.as_json
    # => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
    #     "created_at" => "2006/08/01", "awesome" => true}
    
    ActiveRecord::Base.include_root_in_json = true
    
    user.as_json
    # => { "user" => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
    #                  "created_at" => "2006/08/01", "awesome" => true } }
    

    【讨论】:

    • 这些不是您要查找的值。
    • 是的,这是一个例子。我认为他的 Hash 也是错误的
    【解决方案3】:

    试试这个,

     placements = [<Placement id: 1, employee_name: 'John', month: "2014-02-01",position: 2>, 
        <Placement id: 2, employee_name: 'John', month: "2014-01-01", position: 2>, 
        <Placement id: 3, employee_name: 'Jill', month: "2014-02-01", position: 3>,
        <Placement id: 4, employee_name: 'Jill', month: "2014-01-01", position: 1>
        <Placement id: 5, employee_name: 'Fred', month: "2014-02-01", position: 1>]
    
        placements.map!{|placement| placement.attributes}
    

    【讨论】:

    • 我也有类似的回答:placements.map(&amp;:attributes);然而,看起来 OP 正在询问分组。
    【解决方案4】:

    我建议你做数据库分组而不是在代码中分组,因为它更有效。

    如果您使用mysql,您可以执行以下操作:

    (感谢:https://stackoverflow.com/a/14806663/226255

    r = Placement.connection.select_all(
     "select date_format(month, '%Y-%m') as monthy,
      GROUP_CONCAT(Concat_Ws('=', employee_name, position)) AS place 
      from placements 
      group by year(month), month(month)")
    
    => [{"monthy"=>"2014-01", "placement"=>"John=2,Jill=1"},
     {"monthy"=>"2014-02", "placement"=>"John=2,Jill=3,Fred=1"}]
    

    在此处检查 sqlfiddle: http://www.sqlfiddle.com/#!2/088e7/1/0

    现在,在代码中,转换为与您的问题类似的哈希:

    r.map { |m| 
      h = { :month => m["monthy"] }
      m["placement"].split(',').each { |i| 
      k, v = i.split('='); h[k] = v.to_i }; h 
    }
    
    => [{:month=>"2014-01", "John"=>2, "Jill"=>1},
    {:month=>"2014-02", "John"=>2, "Jill"=>3, "Fred"=>1}]
    

    【讨论】:

    • @jumpingcode 为什么不呢?我刚试了一下,它确实收集了活动记录对象的所有属性
    • 是的.. OP 说他有一个Placement 模型所以它确实有respond_to? :attributes
    猜你喜欢
    • 2020-12-26
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 2023-04-01
    • 1970-01-01
    • 2018-03-12
    • 2015-09-10
    • 1970-01-01
    相关资源
    最近更新 更多