将 2 个散列与相同的键结合起来
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}
我希望新哈希看起来像:
{"12 am"=> 0, 0}
至少那是我认为我想要的。我正在尝试合并这两个哈希值,以便可以在 table.
中显示数据
我知道我需要更改此代码,但这就是我现在在视图中使用的内容。
<% @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
将return{'12 am' => [0,0], '1 am' => [0,0], ... }
首先,我认为 {"12 am"=> 0, 0}
是指一个哈希,其每个键都是一个小时,每个值都是一个包含两个元素的数组,一个代表该小时内的清洁次数,另一个代表该小时内的清洁次数润滑油。如果是这种情况,它应该是这样的:{"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]}
您还可以为每个值使用哈希来提高可读性并防止错误:(记住使用哪个哈希键比记住哪个数组索引更容易。)
@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 }
据推测,table 具有来自每个按小时排序(按键插入时间)的哈希的键值对,因此您希望计算以下内容:
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
构造您的 table.
但是,这要求每个散列的键的插入顺序都按照显示的顺序。写成下面这样比较稳妥
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]]
如果您希望像示例中那样在 table 中表达小时数,您可以使用一种简单的方法:
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"]
构建你的table.
假设您稍后决定 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 小时的值,因此您可以按顺序创建数组而不是散列(我的偏好)。
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]
Hash#merge
这个问题已经有很多很好的答案,但我有点奇怪,还没有人提到 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}}
来源:
我想合并 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}
我希望新哈希看起来像:
{"12 am"=> 0, 0}
至少那是我认为我想要的。我正在尝试合并这两个哈希值,以便可以在 table.
中显示数据我知道我需要更改此代码,但这就是我现在在视图中使用的内容。
<% @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
将return{'12 am' => [0,0], '1 am' => [0,0], ... }
首先,我认为 {"12 am"=> 0, 0}
是指一个哈希,其每个键都是一个小时,每个值都是一个包含两个元素的数组,一个代表该小时内的清洁次数,另一个代表该小时内的清洁次数润滑油。如果是这种情况,它应该是这样的:{"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]}
您还可以为每个值使用哈希来提高可读性并防止错误:(记住使用哪个哈希键比记住哪个数组索引更容易。)
@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 }
据推测,table 具有来自每个按小时排序(按键插入时间)的哈希的键值对,因此您希望计算以下内容:
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
构造您的 table.
但是,这要求每个散列的键的插入顺序都按照显示的顺序。写成下面这样比较稳妥
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]]
如果您希望像示例中那样在 table 中表达小时数,您可以使用一种简单的方法:
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"]
构建你的table.
假设您稍后决定 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 小时的值,因此您可以按顺序创建数组而不是散列(我的偏好)。
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]
Hash#merge
这个问题已经有很多很好的答案,但我有点奇怪,还没有人提到 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}}
来源: