Ruby: как преобразовать строку в логическое значение


У меня есть значение, которое будет одной из четырех вещей: boolean true, boolean false, строка "true" или строка "false". Я хочу преобразовать строку в логическое значение, если это строка, в противном случае оставьте ее неизмененной. Другими словами:

"истина" должна стать истиной

"false" должно стать false

истина должна оставаться истиной

false должен оставаться false

10 53

10 ответов:

def true?(obj)
  obj.to_s == "true"
end

Если вы используете рельсы 5, Вы можете сделать ActiveModel::Type::Boolean.new.cast(value).

в Rails 4.2, использовать ActiveRecord::Type::Boolean.new.type_cast_from_user(value).

поведение немного отличается, как и в Rails 4.2, проверяются истинное значение и ложные значения. В Rails 5 проверяются только ложные значения-если значения не равны нулю или не соответствуют ложному значению, оно считается истинным. Ложные значения одинаковы в обеих версиях: FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"]

Рельсы 5 Источник: https://github.com/rails/rails/blob/5-1-stable/activemodel/lib/active_model/type/boolean.rb

if value.to_s == 'true'
  true
elsif value.to_s == 'false'
  false
end
h = { "true"=>true, true=>true, "false"=>false, false=>false }

["true", true, "false", false].map { |e| h[e] }
  #=> [true, true, false, false] 

Я часто использовал этот шаблон для расширения основного поведения Ruby, чтобы упростить преобразование произвольных типов данных в логические значения, что делает его очень легким для работы с различными параметрами URL и т. д.

class String
  def to_boolean
    ActiveRecord::Type::Boolean.new.cast(self)
  end
end

class NilClass
  def to_boolean
    false
  end
end

class TrueClass
  def to_boolean
    true
  end

  def to_i
    1
  end
end

class FalseClass
  def to_boolean
    false
  end

  def to_i
    0
  end
end

class Integer
  def to_boolean
    to_s.to_boolean
  end
end

Итак, допустим, у вас есть параметр foo что может быть:

  • целое число (0-ложь, все остальные-истина)
  • a true boolean (true/false)
  • строка ("true", "false", "0", "1", "правда", "Ложь")
  • Нил

вместо того, чтобы использовать кучу условных операторов, вы можете просто позвонить foo.to_boolean и это сделает остальную часть магии для вас.

в Rails я добавляю это в инициализатор с именем core_ext.rb почти во всех моих проектах, так как этот шаблон настолько распространен.

## EXAMPLES

nil.to_boolean     == false
true.to_boolean    == true
false.to_boolean   == false
0.to_boolean       == false
1.to_boolean       == true
99.to_boolean      == true
"true".to_boolean  == true
"foo".to_boolean   == true
"false".to_boolean == false
"TRUE".to_boolean  == true
"FALSE".to_boolean == false
"0".to_boolean     == false
"1".to_boolean     == true
true.to_i          == 1
false.to_i         == 0

Не думай слишком много:

bool_or_string.to_s == "true"  

и

"true".to_s == "true"   #true
"false".to_s == "true"  #false 
true.to_s == "true"     #true
false.to_s == "true"    #false

вы также можете добавить ".downcase, " если вы беспокоитесь о заглавных буквах.

хотя мне нравится хэш-подход (я использовал его в прошлом для подобных вещей), учитывая, что вы действительно заботитесь только о сопоставлении истинных значений - поскольку - все остальное ложно - вы можете проверить включение в массив:

value = [true, 'true'].include?(value)

или если другие значения можно считать истинными:

value = [1, true, '1', 'true'].include?(value)

вам придется делать другие вещи, если ваш оригинал value может быть смешанный случай:

value = value.to_s.downcase == 'true'

но опять же, для вашего конкретного описания вашей проблемы, вы могли бы вам сойдет с рук этот последний пример в качестве вашего решения.

драгоценный камень, как https://rubygems.org/gems/to_bool может быть использован, но он может быть легко записан в одной строке с помощью регулярного выражения или тернарного.

пример регулярного выражения:

boolean = (var.to_s =~ /^true$/i) == 0

троичная пример:

boolean = var.to_s.eql?('true') ? true : false

преимущество метода регулярных выражений является то, что регулярные выражения являются гибкими и могут соответствовать различные модели. Например, если вы подозреваете, что var может быть любым из "True", "False", "T", "F", " t " или "f", то вы можете изменить регулярное выражение:

boolean = (var.to_s =~ /^[Tt].*$/i) == 0

в rails, я ранее делал что-то вроде этого:

class ApplicationController < ActionController::Base
  # ...

  private def bool_from(value)
    !!ActiveRecord::Type::Boolean.new.type_cast_from_database(value)
  end
  helper_method :bool_from

  # ...
end

что хорошо, если вы пытаетесь сопоставить свои логические сравнения строк таким же образом, как rails для вашей базы данных.

а как насчет smthing, как:

boolean_str = 'false'
boolean = eval(boolean_str)