[英]Combine 2 hashes with the same key
我想组合 2 个具有相同键的哈希。
@clean_by_hour = Sale.where(item_name: clean).group_by_hour_of_day(:complete_time, format: "%-l %P").count
=> {"12 am"=>0, "1 am"=>0, "2 am"=>0, "3 am"=>0, "4 am"=>0, "5 am"=>0, "6 am"=>0, "7 am"=>0, "8 am"=>4, "9 am"=>14, "10 am"=>19, "11 am"=>10, "12 pm"=>19, "1 pm"=>16, "2 pm"=>13, "3 pm"=>18, "4 pm"=>7, "5 pm"=>4, "6 pm"=>4, "7 pm"=>0, "8 pm"=>0, "9 pm"=>0, "10 pm"=>0, "11 pm"=>0}
@lube_by_hour = Sale.where(item_name: lube).group_by_hour_of_day(:complete_time, format: "%-l %P").count
=> {"12 am"=>0, "1 am"=>0, "2 am"=>0, "3 am"=>0, "4 am"=>0, "5 am"=>0, "6 am"=>0, "7 am"=>0, "8 am"=>3, "9 am"=>4, "10 am"=>10, "11 am"=>14, "12 pm"=>10, "1 pm"=>8, "2 pm"=>5, "3 pm"=>20, "4 pm"=>4, "5 pm"=>2, "6 pm"=>0, "7 pm"=>0, "8 pm"=>0, "9 pm"=>0, "10 pm"=>0, "11 pm"=>0}
我希望新的 hash 看起来像:
{"12 am"=> 0, 0}
至少这是我认为我想要的。 我正在尝试组合这 2 个哈希,以便可以在表格中显示数据。
我知道我需要更改此代码,但这是我现在在视图中使用的内容。
<% @clean_by_hour.each do |hour, count| %>
<% if count != 0 %>
<tr>
<td><%= hour %></td>
<td><%= count %></td>
<% end %>
<% end %>
<% @lube_by_hour.each do |hour, count| %>
<% if count != 0 %>
<td><%= count %></td>
<% end %>
<% end %>
</tr>
谢谢!
您可以为此使用#each_with_object
。 不确定这是否是最好的方法,但它可以让你得到你想要的。
@clean_by_hour.each_with_object({}) do |(k,v), acc|
acc[k] ||= []
acc[k] << v
acc[k] << @lube_by_hour[k]
acc[k].compact
end
将返回{'12 am' => [0,0], '1 am' => [0,0], ... }
首先,我认为{"12 am"=> 0, 0}
你的意思是一个 Hash ,它的每个键都是一个小时,每个值都是一个包含两个元素的数组,一个代表那个小时的清洁次数,另一个代表润滑油的数量。 如果是这种情况,它应该是这样的: {"12 am"=> [0, 0]}
(每个值周围都有[
和]
)
你可以这样做:
@count_by_hour = @clean_by_hour.keys.each_with_object({}) do |k, h|
h[k] = [@clean_by_hour[k], @lube_by_hour[k]]
end
@count_by_hour # =>
{"12 am"=>[0, 0],
"1 am"=>[0, 0],
"2 am"=>[0, 0],
"3 am"=>[0, 0],
"4 am"=>[0, 0],
"5 am"=>[0, 0],
"6 am"=>[0, 0],
"7 am"=>[0, 0],
"8 am"=>[4, 3],
"9 am"=>[14, 4],
"10 am"=>[19, 10],
"11 am"=>[10, 14],
"12 pm"=>[19, 10],
"1 pm"=>[16, 8],
"2 pm"=>[13, 5],
"3 pm"=>[18, 20],
"4 pm"=>[7, 4],
"5 pm"=>[4, 2],
"6 pm"=>[4, 0],
"7 pm"=>[0, 0],
"8 pm"=>[0, 0],
"9 pm"=>[0, 0],
"10 pm"=>[0, 0],
"11 pm"=>[0, 0]}
您还可以对每个值使用 Hash 以提高可读性并防止错误:(记住使用哪个 Hash 键比使用哪个数组索引更容易。)
@count_by_hour = @clean_by_hour.keys.each_with_object({}) do |k, h|
h[k] = { clean: @clean_by_hour[k], lube: @lube_by_hour[k] }
end
@count_by_hour # =>
{"12 am"=>{:clean=>0, :lube=>0},
"1 am"=>{:clean=>0, :lube=>0},
"2 am"=>{:clean=>0, :lube=>0},
"3 am"=>{:clean=>0, :lube=>0},
"4 am"=>{:clean=>0, :lube=>0},
"5 am"=>{:clean=>0, :lube=>0},
"6 am"=>{:clean=>0, :lube=>0},
"7 am"=>{:clean=>0, :lube=>0},
"8 am"=>{:clean=>4, :lube=>3},
"9 am"=>{:clean=>14, :lube=>4},
"10 am"=>{:clean=>19, :lube=>10},
"11 am"=>{:clean=>10, :lube=>14},
"12 pm"=>{:clean=>19, :lube=>10},
"1 pm"=>{:clean=>16, :lube=>8},
"2 pm"=>{:clean=>13, :lube=>5},
"3 pm"=>{:clean=>18, :lube=>20},
"4 pm"=>{:clean=>7, :lube=>4},
"5 pm"=>{:clean=>4, :lube=>2},
"6 pm"=>{:clean=>4, :lube=>0},
"7 pm"=>{:clean=>0, :lube=>0},
"8 pm"=>{:clean=>0, :lube=>0},
"9 pm"=>{:clean=>0, :lube=>0},
"10 pm"=>{:clean=>0, :lube=>0},
"11 pm"=>{:clean=>0, :lube=>0}}
让我们首先简化您的示例:
clean_by_hour = { "12 am"=>0, "1 am"=>3, "2 am"=>0, "3 am"=>5 }
lube_by_hour = { "12 am"=>0, "1 am"=>4, "2 am"=>0, "3 am"=>2 }
据推测,该表具有每个 hash 按小时排序(按键插入时间)的键值对,因此您希望计算以下内容:
hours = clean_by_hour.keys
#=> ["12 am", "1 am", "2 am", "3 am"]
clean_values = clean_by_hour.values
#=> [0, 3, 0, 5]
lube_values = lube_by_hour.values
#=> [0, 4, 0, 2]
arr = clean_values.zip(lube_values)
#=> [[0, 0], [3, 4], [0, 0], [5, 2]]
然后使用hours
和arr
来构建您的表格。
但是,这要求每个 hash 的键的插入顺序是所示的顺序。 写以下内容会更安全。
hours = ["12 am", "1 am", "2 am", "3 am"]
clean_values = clean_by_hour.values_at(*hours)
#=> [0, 3, 0, 5]
lube_values = lube_by_hour.values_at(*hours)
#=> [0, 4, 0, 2]
arr = clean_values.zip(lube_values)
#=> [[0, 0], [3, 4], [0, 0], [5, 2]]
无论散列中键值对的顺序如何,这都有效。 请参阅Hash#values_at 。
退后一步,您可能会考虑使用 24 小时制以不同方式构建原始哈希。 例如:
clean_by_hour = { 0=>0, 1=>3, 12=>5, 13=>1, 23=>6 }
lube_by_hour = { 0=>0, 1=>4, 12=>3, 13=>2, 23=>3 }
然后
hours = [0, 1, 12, 13, 23]
clean_values = clean_by_hour.values_at(*hours)
#=> [0, 3, 5, 1, 6]
lube_values = lube_by_hour.values_at(*hours)
#=> [0, 4, 3, 2, 3]
arr = clean_values.zip(lube_values)
#=> [[0, 0], [3, 4], [5, 3], [1, 2], [6, 3]]
如果您希望像示例中那样在表格中表达小时数,可以使用一个简单的方法:
def hours_to_str(hour)
case hour
when 0 then "12 am"
when 1..11 then "#{hour} am"
when 12 then "12 pm"
else "#{hour-12} pm"
end
end
hours_to_str(0) #=> "12 am"
hours_to_str(3) #=> "3 am"
hours_to_str(11) #=> "11" am"
hours_to_str(12) #=> "12 pm"
hours_to_str(13) #=> "1 pm"
hours_to_str(23) #=> "11 pm"
然后使用
am_pm_hours = hours.map { |hour| hour_to_str(hour) }
#=> ["12 am", "1 am", "12 pm", "1 pm", "11 pm"]
构建你的表。
假设稍后您决定希望am_pm_hours
为:
["12:00 am", "1:00 am", "12:00 pm", "1:00 pm", "11:00 pm"]
然后您只需要更改方法hours_to_str
,而不是构建哈希clean_by_hour
和lube_by_hour
。
最后,由于您要获取一天中所有 24 小时的值,因此您可以按顺序创建 arrays 而不是哈希(我的偏好)。
clean_by_hour = [0, 3, 5, 3, 1, 6, 2, 7, 1, 2, 3, 4,
5, 1, 8, 2, 6, 9, 1, 5, 8, 9, 3, 6]
lube_by_hour = [0, 4, 6, 3, 1, 4, 2, 3, 4, 4, 1, 0,
3, 2, 4, 1, 4, 2, 7, 5, 3, 6, 9, 3]
这个问题已经有很多很好的答案了,但让我有点奇怪的是,还没有人以块的形式提到 Ruby 的内置Hash#merge 。
请看以下示例:
clean_by_hour = { "12 am" => 0, "1 am" => 4, "2 am" => 21 }
lube_by_hour = { "12 am" => 0, "1 am" => 17, "2 am" => 12 }
clean_by_hour.merge(lube_by_hour) { |_key, old_value, new_value| [old_value, new_value] }
# => {"12 am"=>[0, 0], "1 am"=>[4, 17], "2 am"=>[21, 12]}
clean_by_hour.merge(lube_by_hour) do |_key, clean, lube|
{ clean: clean, lube: lube }
end
# {"12 am"=>{:clean=>0, :lube=>0}, "1 am"=>{:clean=>4, :lube=>17}, "2 am"=>{:clean=>21, :lube=>12}}
资料来源:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.