繁体   English   中英

将 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}

我希望新的 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]]

然后使用hoursarr来构建您的表格。


但是,这要求每个 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_hourlube_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM