【问题标题】:Trim a trailing .0修剪尾随 .0
【发布时间】:2013-08-30 12:32:37
【问题描述】:

我有一个包含零件编号的 Excel 列。这是一个示例

如您所见,它可以是许多不同的数据类型:FloatIntString。我正在使用roo gem 来读取文件。问题是roo 将整数单元格解释为Float,在它们后面添加一个零 (16431 => 16431.0)。我想修剪这个尾随零。我不能使用to_i,因为它会修剪所有需要小数的单元格的尾随数字(上例中的第一行),并会在String行(最后一行)中的字符串char之后剪切所有内容在上面的例子中)。

目前,我有一个方法可以检查单元格的最后两个字符,如果它们是“.0”则修剪它们

def trim(row)
    if row[0].to_s[-2..-1] == ".0"
        row[0] = row[0].to_s[0..-3]
    end
end

这行得通,但感觉很糟糕而且很hacky。将我的 Excel 文件内容转换为 Ruby 数据结构的正确方法是什么?

【问题讨论】:

    标签: ruby excel ruby-2.0 roo-gem


    【解决方案1】:
    def trim num
      i, f = num.to_i, num.to_f
      i == f ? i : f
    end
    
    trim(2.5) # => 2.5
    trim(23) # => 23
    

    或者,从字符串:

    def convert x
      Float(x)
      i, f = x.to_i, x.to_f
      i == f ? i : f
    rescue ArgumentError
      x
    end
    
    convert("fjf") # => "fjf"
    convert("2.5") # => 2.5
    convert("23") # => 23
    convert("2.0") # => 2
    convert("1.00") # => 1
    convert("1.10") # => 1.1
    

    【讨论】:

    • 或者只是 result = result.to_i 如果 result == result.to_i
    【解决方案2】:

    对于那些使用 Rails 的用户,ActionView 具有 number_with_precision 方法,该方法采用 strip_insignificant_zeros: true 参数来处理此问题。

    number_with_precision(13.00, precision: 2,  strip_insignificant_zeros: true)
    # => 13
    number_with_precision(13.25, precision: 2,  strip_insignificant_zeros: true)
    # => 13.25
    

    有关详细信息,请参阅number_with_precision 文档。

    【讨论】:

    • 对于那些专门使用 Rails 的人来说很好的解决方案
    【解决方案3】:

    在大多数情况下,这应该可以满足您的需求:some_value.gsub(/(\.)0+$/, '')

    它会修剪所有尾随零和仅跟零的小数点。否则,它会单独留下字符串。

    它也非常高效,因为它完全基于字符串,不需要浮点或整数转换,假设您的输入值已经是一个字符串:

    Loading development environment (Rails 3.2.19)
    irb(main):001:0> '123.0'.gsub(/(\.)0+$/, '')
    => "123"
    irb(main):002:0> '123.000'.gsub(/(\.)0+$/, '')
    => "123"
    irb(main):003:0> '123.560'.gsub(/(\.)0+$/, '')
    => "123.560"
    irb(main):004:0> '123.'.gsub(/(\.)0+$/, '')
    => "123."
    irb(main):005:0> '123'.gsub(/(\.)0+$/, '')
    => "123"
    irb(main):006:0> '100'.gsub(/(\.)0+$/, '')
    => "100"
    irb(main):007:0> '127.0.0.1'.gsub(/(\.)0+$/, '')
    => "127.0.0.1"
    irb(main):008:0> '123xzy45'.gsub(/(\.)0+$/, '')
    => "123xzy45"
    irb(main):009:0> '123xzy45.0'.gsub(/(\.)0+$/, '')
    => "123xzy45"
    irb(main):010:0> 'Bobby McGee'.gsub(/(\.)0+$/, '')
    => "Bobby McGee"
    irb(main):011:0>
    

    【讨论】:

    • 这是一个很好的答案,我只是先添加一个浮点数到字符串:some_value.to_s.gsub(/(\.)0+$/, '')
    【解决方案4】:

    Numeric values are returned as type :float

    def convert_cell(cell)
      if cell.is_a?(Float)
        i = cell.to_i
        cell == i.to_f ? i : cell
      else
        cell
      end
    end
    
    convert_cell("foobar") # => "foobar"
    convert_cell(123) # => 123
    convert_cell(123.4) # => 123.4
    

    【讨论】:

    • 这和我回答的第一部分一样,只是你不做memoization。
    • 正确。开始写的时候没看到现在编辑了。
    • convert_string("1.00") # => "1.00", convert_string("1.20") # => "1.20"
    • 哦。我会调查的。
    • 再次编辑。它应该只返回单元格的实际值。
    猜你喜欢
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    • 2010-11-26
    • 1970-01-01
    相关资源
    最近更新 更多