如何根据提供的密钥正确映射 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
使用 reduce
或 each_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 它没有用于块计算。这是常见的做法。其他两个块变量 o
和 n
的值在 link 中针对方法 update
.
进行了解释
正则表达式 /[^_]+/
,匹配字符串开头的一个或多个不是 (^
) 下划线的字符。当与方法String#[]一起使用时,我们得到:
"Marketing"[/[^_]+/] #=> "Marketing"
"Marketing_summary"[/[^_]+/] #=> "Marketing"
我的数据是这样的:
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
使用 reduce
或 each_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 它没有用于块计算。这是常见的做法。其他两个块变量 o
和 n
的值在 link 中针对方法 update
.
正则表达式 /[^_]+/
,匹配字符串开头的一个或多个不是 (^
) 下划线的字符。当与方法String#[]一起使用时,我们得到:
"Marketing"[/[^_]+/] #=> "Marketing"
"Marketing_summary"[/[^_]+/] #=> "Marketing"