Определите, является ли строка допустимым значением плавающим

Я столкнулся с этой проблемой и нашел мой обходной путь.

Сначала я попытался использовать max-height. Но есть две проблемы:

  1. Я не совсем уверен, что такое max-height, так как я расширяю текстовый блок неизвестной длины.
  2. Если я установлю max-height слишком большим, при сжатии будет большая задержка.

Затем мой обходной путь:

function toggleBlock(e) {
    var target = goog.dom.getNextElementSibling(e.target);
    if (target.style.height && target.style.height != "0px") { //collapsing
        goog.style.setHeight(target, target.clientHeight);
        setTimeout(function(){
            target.style.height = "0px";
        }, 100);
    } else { //expanding
        target.style.height = "auto";
        //get the actual height
        var height = target.clientHeight;
        target.style.height = "0px";
        setTimeout(function(){
            goog.style.setHeight(target, height);
        }, 100);
        setTimeout(function(){
            //Set this because I have expanding blocks inside expanding blocks
            target.style.height="auto";
        }, 600); //time is set 100 + transition-duration
    }
}

Scss:

div.block {
    height: 0px;
    overflow: hidden;
    @include transition-property(height);
    @include transition-duration(0.5s);
}
30
задан Ben5e 23 June 2009 в 18:49
поделиться

5 ответов

Интересным фактом о мире Ruby является существование проекта Rubinius, который реализует Ruby и его стандартную библиотеку в основном на чистом Ruby. В результате у них есть чистая Ruby-реализация Kernel # Float, которая выглядит так:

def Float(obj)
  raise TypeError, "can't convert nil into Float" if obj.nil?

  if obj.is_a?(String)
    if obj !~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/
      raise ArgumentError, "invalid value for Float(): #{obj.inspect}"
    end
  end

  Type.coerce_to(obj, Float, :to_f)
end

Это дает вам регулярное выражение, которое соответствует внутренней работе, которую Ruby выполняет при запуске Float (), но без исключения. Итак, теперь вы можете сделать:

class String
  def nan?
    self !~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/
  end
end

В этом решении хорошо то, что, поскольку Rubinius запускается и передает RubySpec, вы знаете, что это регулярное выражение обрабатывает крайние случаи, которые обрабатывает сам Ruby, и вы можете без страха вызывать to_f в строке !

28
ответ дан 27 November 2019 в 23:15
поделиться

Умм, если вам не нужны исключения, то, возможно,:

def is_float?(fl)
   fl =~ /(^(\d+)(\.)?(\d+)?)|(^(\d+)?(\.)(\d+))/
end

Поскольку OP специально просил решение без исключений. Решение на основе Regexp незначительно медленное:

require "benchmark"
n = 500000

def is_float?(fl)
  !!Float(fl) rescue false
end

def is_float_reg(fl)
  fl =~ /(^(\d+)(\.)?(\d+)?)|(^(\d+)?(\.)(\d+))/
end

Benchmark.bm(7) do |x|
  x.report("Using cast") {
    n.times do |i|
      temp_fl = "#{i + 0.5}"
      is_float?(temp_fl)
    end
  }
  x.report("using regexp") {
    n.times do |i|
      temp_fl = "#{i + 0.5}"
      is_float_reg(temp_fl)
    end
  }
end

Результаты:

5286 snippets:master!? % 
             user     system      total        real
Using cast  3.000000   0.000000   3.000000 (  3.010926)
using regexp  5.020000   0.000000   5.020000 (  5.021762)
3
ответ дан 27 November 2019 в 23:15
поделиться

Вот один способ:

class String
  def valid_float?
    # The double negation turns this into an actual boolean true - if you're 
    # okay with "truthy" values (like 0.0), you can remove it.
    !!Float(self) rescue false
  end
end

"a".valid_float? #false
"2.4".valid_float? #true

Если вы хотите избежать «обезьяны-патча» String, вы всегда можете, конечно, сделать это методом класса некоторого модуля, которым вы управляете:

module MyUtils
  def self.valid_float?(str)
    !!Float(str) rescue false
  end
end
MyUtils.valid_float?("a") #false
36
ответ дан 27 November 2019 в 23:15
поделиться

Я попытался добавить это в качестве комментария, но, по-видимому, в комментариях нет форматирования:

с другой стороны, почему бы просто не использовать это как функцию преобразования, например

class String
  def to_float
    Float self rescue (0.0 / 0.0)
  end
end
"a".to_float.nan? => true

, которая конечно, это то, чего вы не хотели делать в первую очередь. Думаю, ответ таков: «вам нужно написать свою собственную функцию, если вы действительно не хотите использовать обработку исключений, но зачем вам это делать?»

1
ответ дан 27 November 2019 в 23:15
поделиться
# Edge Cases:
# numeric?"Infinity" => true is_numeric?"Infinity" => false


def numeric?(object)
true if Float(object) rescue false
end

#Possibly faster alternative
def is_numeric?(i)
i.to_i.to_s == i || i.to_f.to_s == i
end
8
ответ дан 27 November 2019 в 23:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: