【问题标题】:Ruby group hashes by value of keyRuby 按键值分组哈希
【发布时间】:2011-10-06 03:24:47
【问题描述】:

我有一个数组,它是由 MongoDB 执行的 map/reduce 方法输出的,它看起来像这样:

[{"minute"=>30.0, "hour"=>15.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>0.0, "count"=>299.0}, 
{"minute"=>30.0, "hour"=>15.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>10.0, "count"=>244.0}, 
{"minute"=>30.0, "hour"=>15.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>1.0, "count"=>204.0}, 
{"minute"=>45.0, "hour"=>15.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>0.0, "count"=>510.0}, 
{"minute"=>45.0, "hour"=>15.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>10.0, "count"=>437.0}, 
{"minute"=>0.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>0.0, "count"=>469.0}, 
{"minute"=>0.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>10.0, "count"=>477.0}, 
{"minute"=>15.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>0.0, "count"=>481.0}, 
{"minute"=>15.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>10.0, "count"=>401.0}, 
{"minute"=>30.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>0.0, "count"=>468.0}, 
{"minute"=>30.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>10.0, "count"=>448.0}, 
{"minute"=>45.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>0.0, "count"=>485.0}, 
{"minute"=>45.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "type"=>10.0, "count"=>518.0}] 

您会注意到type 有三个不同的值,在本例中为012,现在要做的是将这个哈希数组按其@987654327 的值分组@key,所以例如这个数组最终看起来像:

{
  :type_0 => [
    {"minute"=>30.0, "hour"=>15.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>299.0}, 
    {"minute"=>45.0, "hour"=>15.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>510.0}, 
    {"minute"=>0.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>469.0}, 
    {"minute"=>15.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>481.0}, 
    {"minute"=>30.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>468.0}, 
    {"minute"=>45.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>485.0}
  ],

  :type_1 => [
    {"minute"=>30.0, "hour"=>15.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>204.0}
  ],

  :type_10 => [
    {"minute"=>30.0, "hour"=>15.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>244.0}, 
    {"minute"=>45.0, "hour"=>15.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>437.0},
    {"minute"=>0.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>477.0}, 
    {"minute"=>15.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>401.0}, 
    {"minute"=>30.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>448.0}, 
    {"minute"=>45.0, "hour"=>16.0, "date"=>5.0, "month"=>9.0, "year"=>2011.0, "count"=>518.0}
  ]
} 

所以我知道这些示例数组确实很大,但我认为这可能是一个比我想象的更简单的问题

所以基本上每个哈希数组都将按其type 键的值分组,然后作为带有每种类型数组的哈希返回,任何帮助都会非常有帮助,甚至只是一些有用的提示将不胜感激。

【问题讨论】:

标签: ruby mongodb hash mongodb-ruby


【解决方案1】:
array.group_by {|x| x['type']}

或者如果你想要符号键,你甚至可以

array.group_by {|x| "type_#{x['type']}".to_sym}

我认为这最能表达“所以基本上每个哈希数组都会按其类型键的值分组,然后作为哈希返回每种类型的数组”,即使它在输出哈希中单独留下:type 键。

【讨论】:

  • 它不会产生问题中的输出,并且在 Ruby 1.8 中不起作用
  • 这将分组,但不会删除响应中的“类型”。我不介意,因为它很简单,但它不能回答问题,tbh。
【解决方案2】:

大概是这样的吧?

mangled = a.group_by { |h| h['type'].to_i }.each_with_object({ }) do |(k,v), memo|
    tk = ('type_' + k.to_s).to_sym
    memo[tk] = v.map { |h| h = h.dup; h.delete('type'); h }
end

或者如果您不关心保留原始数据:

mangled = a.group_by { |h| h['type'].to_i }.each_with_object({ }) do |(k,v), memo|
    tk = ('type_' + k.to_s).to_sym
    memo[tk] = v.map { |h| h.delete('type'); h } # Drop the h.dup in here
end

【讨论】:

    【解决方案3】:
    by_type = {}
    
    a.each do |h|
       type = h.delete("type").to_s
       # type = ("type_" + type ).to_sym
    
       by_type[ type ] ||= []
       by_type[ type ] << h      # note: h is modified, without "type" key
    
    end
    

    注意:这里的哈希键略有不同,我直接使用类型值作为键

    如果您必须拥有示例中的哈希键,则可以添加被注释掉的行。


    P.S.:我刚刚看到了 Tapio 的解决方案——它非常好而且很短!请注意,它仅适用于 Ruby >= 1.9

    【讨论】:

    • 为什么不只是a.group_by {|x| x['type']}
    • 因为它不会删除“类型”键?我不认为这真的很重要,不是吗?
    • @Tapio:在他的示例中,他期望“类型”键在此过程中从哈希中删除...是的,我同意,并不重要.. group_by()又新又好吃,谢谢! +1
    【解决方案4】:

    group_by 收集一个可枚举的集合,按块的结果分组。您不限于简单地获取此块中的键值,因此如果您想在这些集合中省略 'type',您可以这样做,例如:

    array.group_by {|x| "type_#{x.delete('type').to_i}".to_sym}
    

    这将完全符合您的要求。

    高级:这有点超出了问题的范围,但是如果您想保留原始数组,则必须复制其中的每个对象。这样就可以了:

    array.map(&:dup).group_by {|x| "type_#{x.delete('type').to_i}".to_sym}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-18
      • 2020-10-09
      • 1970-01-01
      • 2013-07-06
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      相关资源
      最近更新 更多