更新迭代器中的哈希值,所有值将是rails中的最后一次迭代

时间:2019-04-05 01:20:34

标签: ruby-on-rails ruby

我尝试使用迭代器更新哈希值,就像我创建的哈希一样:

@period = Date.new(2019,3,1)..Date.new(2019,3,31)

@deals = Deal.includes(:staff).where(shop_id:1, created_at:@period).group_by{|t| t.staff}

data = {}
 staff_id_container = {
  total:{item1: 0, item2: 0, item3: 0}
 }

 Staff.where(shop_id: 1).select(:id).each do |staff|
  staff_id_container[staff.id] = {item1:0, item2:0, item3:0}
 end

 @period.each do |date|
  data[date] = staff_id_container.dup
 end

,可以通过三种方法来更新两层嵌套结构:

1。直接替换值

@deals.each do |staff, deals_by_staff|
  deals_by_staff.group_by{|t| t.created_at.to_date}.each do |date, selected_deals|
   data[date][staff.id] = {
    item1: select_deals.select{|deal| deal.item == "item1"}.count
    item2: select_deals.select{|deal| deal.item == "item2"}.count
    item3: select_deals.select{|deal| deal.item == "item3"}.count
   }
  end
 end

2。使用合并

@deals.each do |staff, deals_by_staff|
  deals_by_staff.group_by{|t| t.created_at.to_date}.each do |date, selected_deals|
   data[date][staff.id].merge!({
    item1: select_deals.select{|deal| deal.item == "item1"}.count
    item2: select_deals.select{|deal| deal.item == "item2"}.count
    item3: select_deals.select{|deal| deal.item == "item3"}.count
   })
  end
 end

3。使用“ =”进行声明

@deals.each do |staff, deals_by_staff|
  deals_by_staff.group_by{|t| t.created_at.to_date}.each do |date, selected_deals|
    data[date][staff.id][:item1] = select_deals.select{|deal| deal.item == "item1"}.count
    data[date][staff.id][:item2] = select_deals.select{|deal| deal.item == "item2"}.count
    data[date][staff.id][:item3] = select_deals.select{|deal| deal.item == "item3"}.count
  end
 end

第一种方法可行,但是如果data[date][staff.id]的初始值为{item1: 0,item2: 0,item3: 0, item4: 0}并且item4将被覆盖。

第二和第三种方式返回错误的值,它们都让每个日期的所有值都成为上一个日期的重复。

如上所示:

{
 2019-03-01:{
  staff_1:{item1: 0, item2: 3, item3: 1, item4: 5},
  staff_2:{item1: 1, item2: 4, item3: 2, item4: 7},
 },
 2019-03-02:{
  staff_1:{item1: 0, item2: 3, item3: 1, item4: 5},
  staff_2:{item1: 1, item2: 4, item3: 2, item4: 7},
 }
} 

如果我只想修改data[date][staff_id]之类的data[date][staff_id][:item1]的一个键或向data[date][staff_id]中添加新的键,我需要使用 排第二或第三。

第二和第三方式的问题是什么?

2 个答案:

答案 0 :(得分:0)

在构建

之类的数据时,尝试用dup替换deep_dup
data[date] = staff_id_container.deep_dup

https://apidock.com/rails/Hash/deep_dup

答案 1 :(得分:0)

按照以下第一种方式:

@deals.each do |staff, deals_by_staff|
  deals_by_staff.group_by{|t| t.created_at.to_date}.each do |date, selected_deals|
   data[date][staff.id] = {
    item1: select_deals.select{|deal| deal.item == "item1"}.count
    item2: select_deals.select{|deal| deal.item == "item2"}.count
    item3: select_deals.select{|deal| deal.item == "item3"}.count
   }
  end
 end

如果要添加或更改深度哈希中的值,我建议采用这种方式:

@deals.each do |staff, deals_by_staff|
  deals_by_staff.group_by{|t| t.created_at.to_date}.each do |date, selected_deals|
   temp = data[date][staff.id].dup
   temp[:item4] = selected_deals.select{|deal| deal.item == "item4"}.count
   data[date][staff.id] = temp
  end
 end