我可以使用Ruby的map方法和一种case语句来构建一个智能数组吗?

时间:2014-05-01 16:03:48

标签: ruby-on-rails ruby arrays map refactoring

以下是我编写代码的方式:

sevendas = sixdas = fivedas = fourdas = threedas = twodas = onedas = todays = 0
@sat = List.all({:company_id => params[:id], :sat => true, :created_at => {:$gte => (time - 1.week)}})
@sat.each do |s|       
    if s["created_at"].strftime("%m-%d-%Y") == (time-1.week).strftime("%m-%d-%Y")
        sevendas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time-6.days).strftime("%m-%d-%Y")
        sixdas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time-5.days).strftime("%m-%d-%Y")
        fivedas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time-4.days).strftime("%m-%d-%Y")
        fourdas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time-3.days).strftime("%m-%d-%Y")
        threedas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time-2.days).strftime("%m-%d-%Y")
        twodas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time-1.day).strftime("%m-%d-%Y")
        onedas += 1
    elsif s["created_at"].strftime("%m-%d-%Y") == (time).strftime("%m-%d-%Y")
        todays += 1
    end
end
@tot_sat = []
@tot_sat.push( sevendas, sixdas, fivedas, fourdas, threedas, twodas, onedas, todays )

这很好用。我现在正在做的是改进我的代码并学习更有效的方法来编写这些类型的块。

我觉得我可以在这里使用地图 - 它是我当天的方法,试图更好地处理它。

2 个答案:

答案 0 :(得分:2)

@tot_sat = @sat.group_by do |s|
  (time - s["created_at"]).to_i / 1.day
end.select do |diff, _| 
  diff < 8 
end.sort_by do |diff, _| 
  - diff 
end.map do |_, entries| 
  entries.count 
end

此解决方案按条件与time的天数差异对条目进行分组,然后计算每天差异中的条目数。


<强>更新
如果并非所有值(0-7)都有条目,则上面的代码有问题。在这种情况下,阵列将更短。为了避免这种情况,我们将使用不同的策略将分组的哈希值转换为数组:

grouped_sat = @sat.group_by do |s|
  (time - s["created_at"]).to_i / 1.day
end

@tot_sat = (0..7).map { |days| (grouped_sat[days] || []).count }

在这种策略中,0到7之间的所有值依次计算具有查询间隔的元素数量,默认为0(空数组的长度),如果没有元素查询间隔。

答案 1 :(得分:1)

如果您想按日期比较时间戳,请使用to_date。在不了解代码上下文的任何其他内容的情况下,只需计算s['created_at'].to_date一次并使用case语句即可显着清理它:

sevendas = sixdas = fivedas = fourdas = threedas = twodas = onedas = todays = 0
@sat = List.all(company_id: params[:id], sat: true, created_at: {$gte: (time - 1.week)}})
today = time.to_date
@sat.each do |s|
  case s['created_at'].to_date
  when today - 1.week then sevendas += 1
  when today - 6.days then sixdas += 1
  when today - 5.days then fivedas += 1
  when today - 4.days then fourdas += 1
  when today - 3.days then threedas += 1
  when today - 2.days then twodas += 1
  when today - 1.day then onedas += 1
  when today then todays += 1
  end
end
@tot_sat = []
@tot_sat.push( sevendas, sixdas, fivedas, fourdas, threedas, twodas, onedas, todays )

您可以进一步重构它以删除丑陋的sevendas = sixdas = fivedas = ...事物并将值存储在数组中。