如何根据提供的密钥正确映射 ruby 哈希

How to map ruby hashes correctly based on key provided

我的数据是这样的:

h = { themes_data: {
    Marketing: [
        {
            id: 68,
            projectno: "15",
        }
    ],
    Produktentwicklung: [
        {
            id: 68,
            projectno: "15",
        },
        {
            id: 4,
            projectno: "3",
        }
    ],
    Marketing_summary: [
        {
            ges: {
                result: "47.6"
            },
            theme: "Marketing"
        }
    ],
    Produktentwicklung_summary: [
        {
            ges: {
                result: "87.7"
            },
            theme: "Produktentwicklung"
        }
    ]
  }
}

我的输出应该是这样的:

{ "marketing" => [
    {
      id: 68,
      projectno: "15",
    },
    {
      ges: { 
        result: "47.6"
      },
      theme: "Marketing"
    }
  ],
  "Produktentwicklung" => [
    {
      id: 68,
      projectno: "15"
    },
    {
      id: 4,
      projectno: "3",
    },
    {
      ges: {
        result: "87.7"
      },
      theme: "Produktentwicklung"
    }
  ]
}

代码:

def year_overview_theme
  branch_hash = {}
  @themes_data.each do |td|
    arr = []
    td[1].map do |dt|
      arr << [{content: dt[:projectno], size: 5, align: :right, background_color: 'D8E5FF'}]
    end
    branch_hash["#{td[0]}"] = arr
  end
  branch_hash
end

问题是它没有迭代正确的哈希键。

例如,我想要:

marketing + marketing_summary as 1 hash and similarly

Produktentwicklung = Produktentwicklung_summary 作为一个哈希,但我的逻辑存在一些问题。

有没有一种方法可以在 2 次迭代后进行检查,

它应该使用 branch_hash["#{td[0]}"] = arr ?

执行 arr << 数据

让我从一个注释开始:在我看来,这更像是应该在 SQL(如果它来自 SQL)而不是 Ruby 中解决的问题。

除此之外,这里有一个应该有效的解决方案:

output = {}

themes_data.each do |theme, projects|
  projects.each do |project|
    key = project[:theme] || theme.to_s
    output[key] ||= [] # make sure the target is initialized
    output[key] << project
  end
end

使用 reduceeach_with_object 可能会有更优雅的解决方案,但这很有效,而且很简单。

keys = themes_data.keys
summary_keys = themes_data.keys.grep(/_summary/)

result = {}.tap do |hash|
  (keys - summary_keys).each do |key|
    hash[key] = themes_data[key] + themes_data["#{key}_summary".to_sym]
  end
end

所需的散列可以构造如下。

h[:themes_data].each_with_object({}) { |(k,v),g| 
  g.update(k.to_s[/[^_]+/]=>v) { |_,o,n| o+n } }
  #=> { "Marketing"=>[
  #       {:id=>68, :projectno=>"15"},
  #       {:ges=>{:result=>"47.6"}, :theme=>"Marketing"}
  #     ],
  #     "Produktentwicklung"=>[
  #       {:id=>68, :projectno=>"15"},
  #       {:id=>4, :projectno=>"3"},
  #       {:ges=>{:result=>"87.7"}, :theme=>"Produktentwicklung"}
  #     ]
  #   } 

这使用 Hash#update(又名 merge)的形式,它使用一个块来确定要合并的两个哈希中存在的键的值。这个块是:

{ |_,o,n| o+n }

第一个块变量 _ 是公共键。我用下划线(一个有效的局部变量)表示它来告诉 reader 它没有用于块计算。这是常见的做法。其他两个块变量 on 的值在 link 中针对方法 update.

进行了解释

正则表达式 /[^_]+/,匹配字符串开头的一个或多个不是 (^) 下划线的字符。当与方法String#[]一起使用时,我们得到:

"Marketing"[/[^_]+/]         #=> "Marketing"
"Marketing_summary"[/[^_]+/] #=> "Marketing"