简体   繁体   English

将 2 个哈希与相同的键组合

[英]Combine 2 hashes with the same key

I am wanting to combine 2 hashes that have the same keys.我想组合 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}

I am wanting the new hash to look like:我希望新的 hash 看起来像:

{"12 am"=> 0, 0}

At least that is what I think I want.至少这是我认为我想要的。 I am attempting to combine the 2 hashes so that I can display the data in a table.我正在尝试组合这 2 个哈希,以便可以在表格中显示数据。

I know I will need to alter this code, but this is what I am working with right now in the view.我知道我需要更改此代码,但这是我现在在视图中使用的内容。

    <% @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>

Thank you!谢谢!

You could use #each_with_object for this.您可以为此使用#each_with_object Not sure if it's the best way, but it gets you what you want.不确定这是否是最好的方法,但它可以让你得到你想要的。

@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

will return {'12 am' => [0,0], '1 am' => [0,0], ... }将返回{'12 am' => [0,0], '1 am' => [0,0], ... }

First, I think by {"12 am"=> 0, 0} you mean a Hash with each of its keys being an hour and each value an Array with two elements, one representing the number of cleans in that hour and the other the number of lubes.首先,我认为{"12 am"=> 0, 0}你的意思是一个 Hash ,它的每个键都是一个小时,每个值都是一个包含两个元素的数组,一个代表那个小时的清洁次数,另一个代表润滑油的数量。 If that's the case it should be like this: {"12 am"=> [0, 0]} (with [ and ] around each value)如果是这种情况,它应该是这样的: {"12 am"=> [0, 0]} (每个值周围都有[]

You can do that with something like this:你可以这样做:

@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]}

You could also use a Hash for each value to improve the readability and prevent bugs: (It's easier to remember which Hash key to use than which Array index.)您还可以对每个值使用 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}}

Let's start by simplifying your example:让我们首先简化您的示例:

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 }

Presumably, the table has key-value pairs from each hash that ordered (by time of key insertion) by hour, so you wish to compute the following:据推测,该表具有每个 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]]

and then use hours and arr to construct your table.然后使用hoursarr来构建您的表格。


This requires, however, that the insertion order of the keys of each hash are in the order shown.但是,这要求每个 hash 的键的插入顺序是所示的顺序。 It would be safer to write the following.写以下内容会更安全。

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]]

This works regardless of the order of the key-value pairs in the hashes.无论散列中键值对的顺序如何,这都有效。 See Hash#values_at .请参阅Hash#values_at


Stepping back, you might consider constructing your original hashes differently, using a 24-hour clock.退后一步,您可能会考虑使用 24 小时制以不同方式构建原始哈希。 For example:例如:

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 }

then然后

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]]

If you wish to express the hours in your table as in your example, you could use a simple method:如果您希望像示例中那样在表格中表达小时数,可以使用一个简单的方法:

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"

Then use然后使用

am_pm_hours = hours.map { |hour| hour_to_str(hour) }
  #=> ["12 am", "1 am", "12 pm", "1 pm", "11 pm"]

to construct your table.构建你的表。

Suppose that later you decide you want am_pm_hours to be:假设稍后您决定希望am_pm_hours为:

["12:00 am", "1:00 am", "12:00 pm", "1:00 pm", "11:00 pm"]

Then you need only change the method hours_to_str , rather than the construction of the hashes clean_by_hour and lube_by_hour .然后您只需要更改方法hours_to_str ,而不是构建哈希clean_by_hourlube_by_hour


Lastly, since you are obtaining values for all 24 hours of the day, in order, you might create arrays rather than hashes (my preference).最后,由于您要获取一天中所有 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]

Hash#merge哈希#合并

This question already has a lot of great answers, but it is a little bit strange to me that nobody has mentioned Ruby's built-in Hash#merge in its block form yet.这个问题已经有很多很好的答案了,但让我有点奇怪的是,还没有人以块的形式提到 Ruby 的内置Hash#merge

Please, have a look at the following examples:请看以下示例:

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

Sources :资料来源

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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