数组操作(按特定组汇总一列,保持其他列相同)

时间:2011-02-01 14:30:17

标签: ruby-on-rails ruby grouping

我有一个包含name, duration, type, ref_id列的日志表。

我经常更新表格,所以它可能看起来像['bill', 'bob', 'bob', 'jill']列表中的名称,[3, 5, 6, 2]表示持续时间,['man', boy', 'boy', 'girl']表示类型,[1, 2, 2, 3] } for ref_id。

我想操纵我的表,以便我可以添加所有持续时间,以便我得到一个哈希或类似的东西:

{'name' => ['bill', 'bob', 'jill'], 'duration' => [3, 11, 2], 'type' => ['man', 'boy', 'girl'], ref_id => [1, 2, 3]}

我该怎么做?

(更多信息 - 目前我正在做Log.sum(:duration, :group => 'name'),它给我的名字本身就是键(bill,bob,jill)而不是列名,正确的持续时间总和作为它们的值( 3,11,2)。但随后我丢失了剩下的数据......)

我想我可以手动浏览每个日志并添加名称/类型/ ref_id,如果它不在哈希值中,则添加到持续时间。如果是这样,最好的方法是什么?

如果你知道有关rails数组操作/常用习语的好消息来源,那也会很棒!

3 个答案:

答案 0 :(得分:2)

首先注意几个笔记。

您的表格未正确规范化。您应该将此表拆分为(至少)两个:usersdurations。你应该这样做有很多原因,那就是关系数据库101.

此外,您想要的哈希值看起来也不正确,它表明您正在预先分组数据以适合您的演示文稿。将这些结果放在哈希数组中通常比在数组哈希中更合乎逻辑。

现在回答:

使用您的表格,您只需执行GROUP BY:

SELECT name, type, ref_id, SUM(duration) as duration
FROM logs
GROUP BY name, type, ref_id

或使用AR:

durations = Log.find(:all,
  :select => 'name, type, ref_id, SUM(duration) as duration',
  :group => 'name, type, ref_id'
)

为了将其转换为数组的哈希值,您可以使用类似:

的内容
Hash[
  %w{name, type, ref_id, duration}.map{|f|
    [f, durations.map{|h|
      h.attributes[f]
    }]
  }
]

答案 1 :(得分:1)

也许您需要的是这样的东西,它会旋转所有日志条目并收集结果:

# Define attributes we're interested in
operate_on = %w[ name duration type ref_id ]

# Create a new hash with placeholder hashes to collect instances
summary = Hash[operate_on.map { |k| [ k, { } ] }]

Log.all.collect do |log|
  operate_on.each do |attr|
    # Flag this attribute/value pair as having been seen
    summary[attr][log.send(attr)] = true
  end
end

# Extract only the keys, return these as a hash
summary = Hash[summary.map { |key, value| [ key, value.keys ] }]

一种更有效的方法是将此作为几个SELECT DISTINCT(x)调用,而不是实例化这么多模型。

答案 2 :(得分:0)

如果您想要从哈希中保存记录,或者您想要查询表并以此形式返回结果,则不太明白。如果你想得到一个哈希值,那么这应该可行:

Log.all.inject({}) do |hash, l|
  hash['name'] ||= []
  hash['duration'] ||= []
  hash['type'] ||= []
  hash['ref_id'] ||= []
  hash['name'] << l.name
  hash['duration'] << l.duration
  hash['type'] << l.type
  hash['ref_id'] << l.ref_id
  hash
end