Ruby从数组中删除非数值并将rest转换为float

问题描述 投票:2回答:2

我有一个用户输入的字符串,我变成一个数组,然后我遍历数组并删除非数字值。

看起来我的正则表达式匹配工作的时间是一半,而我的to_f永远不会将数组值设置为浮点数。

让我们假设我输入:“1 2 3b c3 4,5t”

puts "Enter Minutes"  
STDOUT.flush  
freq = gets.chomp
freq = freq.split(/\W/) #this creates the array, splitting at non-word chars

p freq #outputs: ["1", "2", "3b", "c3", "4", "", "5t"]

freq.each do |minutes|
        if ( minutes == "" or /\D/.match(minutes) ) then freq.delete(minutes) else minutes.to_f end
end

p freq #outputs: ["1", "2", "c3", "4", "5t"]

我期望的结果是:[1,2,4] #note它们是数字而不是字符

arrays ruby each
2个回答
5
投票

问题是你只是在then条件下而不是在else条件下改变freq。

有一些可以为你改变的方法,它们通常以!结尾:

freq = ["1", "2", "3b", "c3", "4", "", "5t"]
=> ["1", "2", "3b", "c3", "4", "", "5t"]

freq.reject! { |minutes| minutes.match(/\D/) || minutes == "" }.map! { |minutes| minutes.to_f }
=> [1.0, 2.0, 4.0]

4
投票
arr = ["1", "2", "3b", "c3", "4", "", "5t"]

这个问题有两种可能的方法。一种是执行两个步骤:删除所有不是非负整数表示的元素,然后将这些整数转换为浮点数,需要一次通过两个数组中的每一个。另一个是建立一个花车阵列,通过arr一次通过。这可以如下完成。

arr.each_with_object([]) { |s,a| a << s.to_f if s.match?(/\A\d+\z/) }
  #=> [1.0, 2.0, 4.0] 

正则表达式读取,“匹配字符串的开头(锚点\A),后跟一个或多个数字,然后是字符串的结尾(锚点\z)。这与不匹配空字符串或字符相同这不是数字,所以我们可以写:

arr.each_with_object([]) { |s,a| a << s.to_f unless s.empty? or s.match?(/\D/) }
  #=> [1.0, 2.0, 4.0] 

这里两者之间没有太多选择,但有时后一种方法更容易实现。

另一种方式,我不是太喜欢(但值得了解),是使用Kernel#Float方法,然后是Array#compact

arr = ["1", "-2", "3b", "c3", "4.23", "", "5t", "-1.2e3"]

arr.map { |s| Float(s) rescue nil }.compact
  #=> [1.0, -2.0, 4.23, -1200.0]

如图所示,这会将整数或浮点(不仅仅是非负整数)表示的arr元素转换为浮点数(可能需要也可能不需要)。

如果Float(s)不能转换为浮动,ArgumentError会引发s。例如:

Float("3b")
  #=> ArgumentError (invalid value for Float(): "3b")

当发生这种情况时,我在一个内联救援条款中捕获异常,返回nil

一些Rubiests不喜欢内联救援条款,因为它们可以掩盖其他错误。只有救援ArgumentErrors才能解决这个问题:

arr.map do |s|
  begin
    Float(s)
  rescue ArgumentError
    nil
  end
end.compact
  #=> [1.0, -2.0, 4.23, -1200.0]
© www.soinside.com 2019 - 2024. All rights reserved.