【问题标题】:Why does this refactored ruby method return nil? [closed]为什么这个重构的 ruby​​ 方法返回 nil? [关闭]
【发布时间】:2013-05-04 04:21:13
【问题描述】:

我在 Float 类中编写了一个方法,它采用浮点数(秒)并将其转换为倒数计时器。当我这样编写代码时,代码可以正常工作:

class Float
  def to_countdown
    (self % 60) == 1 ? cd_sec = "#{(self % 60).to_i} second" : ( (self % 60).to_i == 0 ? cd_sec = "" : cd_sec = "#{(self % 60).to_i} seconds" )
    ((self/60) % 60) == 1 ? cd_min = "#{((self/60) % 60).to_i} minute" : ( ((self/60) % 60).to_i == 0 ? cd_min = "" : cd_min = "#{((self/60) % 60).to_i} minutes" )
    (self/3600) == 1 ? cd_hour = "#{(self/3600).to_i} hour" : ( (self/3600).to_i == 0 ? cd_hour = "" : cd_hour = "#{(self/3600).to_i} hours" )
    (self/(60*60*24)) == 1 ? cd_day = "#{(self/(60*60*24)).to_i} day" : ( (self/(60*60*24)).to_i == 0 ? cd_day = "" : cd_day = "#{(self/(60*60*24)).to_i} days" )
    countdown = [cd_day, cd_hour, cd_min, cd_sec].reject! {|c| c == nil}
    return countdown.to_sentence
  end
end

509330.546146.to_countdown => "x days, y hours, z minutes, and a seconds"

我想重构它。我的最终结果是:

class Float
  def to_countdown
    s,m,h,d = (self % 60),((self/60) % 60),((self/3600)%24),(self/(60*60*24))
    s == 1 ? cd_sec  = "#{s.to_i} second" : ( s.to_i == 0 ? cd_sec  = "" : cd_sec  = "#{s.to_i} seconds" )
    m == 1 ? cd_min  = "#{m.to_i} minute" : ( m.to_i == 0 ? cd_min  = "" : cd_min  = "#{m.to_i} minutes" )
    h == 1 ? cd_hour = "#{h.to_i} hour"   : ( h.to_i == 0 ? cd_hour = "" : cd_hour = "#{h.to_i} hours" )
    d == 1 ? cd_day  = "#{d.to_i} day"    : ( d.to_i == 0 ? cd_day  = "" : cd_day  = "#{d.to_i} days" )
    countdown = [cd_day, cd_hour, cd_min, cd_sec].reject! {|c| c == nil}
    return countdown.to_sentence
  end
end

当我尝试重构版本时,我得到:

509330.546146.to_countdown => **undefined method `to_sentence' for nil:NilClass>.** 

这意味着countdownnil。我在重构版本中做错了什么?

【问题讨论】:

  • 你可以像这样cd_sec = s==1 ? "#{s.to_i} second" : (s.to_i == 0 ? "" : "#{s.to_i} seconds" ) 进一步重构这些行
  • 不给代码,试读者猜。而是给出输入和预期输出是什么。
  • 抱歉,我会编辑我的代码以显示两者!
  • 虽然 Sergio 的 compact 在这种情况下是更好的选择,但请注意,您可以执行 `reject!(&:nil?) 之类的操作,而不是包含一个块并进行显式比较。

标签: ruby arrays time refactoring null


【解决方案1】:

替换这个

countdown = [cd_day, cd_hour, cd_min, cd_sec].reject! {|c| c == nil}

有了这个

countdown = [cd_day, cd_hour, cd_min, cd_sec].compact

另外,您使用的是 bang 版本。它就地改变数组和can return nil。如果您想继续使用reject,请使用常规版本(非爆炸)。

【讨论】:

  • 非常感谢!这解决了我的问题。这是一个如此明显的答案,以至于我被否决了吗?
  • @SeanLarkin:可能有人这么认为。您正在返回reject! 的结果,因此大多数人的第一个想法是查看reject! 的文档,其中指出如果数组未更改,它将返回nil。但不要让它让你失望。当你是新人时,你就是新人。
  • 很公平!我很欣赏这种洞察力。我只是相信,如果您要投反对票,请解释原因,以便人类(犯错误的人)可以纠正并从中吸取教训,因此忍不住问。
猜你喜欢
  • 2014-01-17
  • 2012-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-05
  • 2018-02-19
  • 2022-10-13
  • 1970-01-01
相关资源
最近更新 更多