Ruby动态解压缩行

时间:2014-04-07 07:42:14

标签: ruby-on-rails ruby hash

我想在变量core_game_fields中的一个位置决定从我的数据库中抓取哪些字段。此字段将始终包含:id,然后它将包含我决定的任何其他内容。我想在一个地方设置这个字段,然后让代码抓住那些字段,然后将它解压缩到哈希中。现在这个代码可以工作了,但你可以看到它意味着我必须硬编码,并重复我想要抓取3次的变量,而不是仅仅1次。

mh = {}

core_game_fields = [:id, :date, :season, :away_team_id, :home_team_id]
stuff = Game.pluck(*core_game_fields)

stuff.each do |id, date, season, away_team_id, home_team_id|
mh[id] = { :date => date,
           :season => season,
           :away_team_id => away_team_id,
           :home_team_id => home_team_id }
end

1 个答案:

答案 0 :(得分:3)

以下是一种方法(Ruby 1.9.3):

mh = stuff.each_with_object({}) do |row,h|
  h[row[0]] = Hash[fields[1, fields.length].zip(row[1, row.length])]
end

以下是它的工作原理:

  1. stuff.each_with_object({}) do |row,h|mh哈希开始,并将其传递给每个哈希 在结果集中迭代一行,以便可以将子哈希添加到其中。请参阅Enumerable#each_with_object

  2. h[row[0]]将行的ID作为子哈希的键。

  3. fields[1, fields.length]切掉除第一个之外的所有字段符号,然后返回 它们就像一个数组,如[:date, :season, :away_team_id, :home_team_id]

  4. 字段符号数组为zipped together,行数据为

    zip(row[1, row.length])] == zip([date_val, season_val, ...etc])
    

    索引0处的元素在子数组中组合在一起,然后索引1,依此类推,直到获得[[:date, date_val], [:season, season_val], ...etc]

  5. Hash[Step #4]将键/值对数组转换为实际哈希值,然后将其分配给行ID的集合哈希h

  6. 如果你不想把它全部放在一行,你可以把它分开一点:

    sub_fields = fields[1, fields.length]
    
    mh = stuff.each_with_object({}) do |row,h|
      id, rest = row[0], row[1, row.length]
      h[id] = Hash[sub_fields.zip rest]
    end