Ruby:如何将字符串转换为布尔值
Posted
技术标签:
【中文标题】Ruby:如何将字符串转换为布尔值【英文标题】:Ruby: How to convert a string to boolean 【发布时间】:2016-07-13 17:41:00 【问题描述】:我有一个值,它将是以下四种情况之一:boolean true、boolean false、字符串“true”或字符串“false”。如果它是字符串,我想将字符串转换为布尔值,否则保持不变。换句话说:
“真”应该变成真
“假”应该变成假
真实应该保持真实
假应该保持假
【问题讨论】:
结果是否有是true
或false
这两个值之一,或者如果结果为真或假就足够了吗?如果是后者,那么 false
已经是假的,true
和 'true'
都是真值,所以结果不正确的唯一值是 'false'
: if input == 'false' then true else input end
应该这样做。
Jorg 的评论很棒,但是我认为对于某些应用程序来说,布尔值必须是真或假,而不仅仅是一个真假值。
Emery,如果你需要返回一个布尔值,你可以在 @Jörg 的表达式前面加上两个“not”:!!(if input == 'false' then true else input end)
。第二个!
将返回值转换为与您想要的相反的布尔值;第一个!
然后进行更正。这个“把戏”由来已久。不是每个人都喜欢它。
【参考方案1】:
if value.to_s == 'true'
true
elsif value.to_s == 'false'
false
end
【讨论】:
您的代码作为单行代码value.to_s == 'true' ? true : false
@sagarpandya82 :永远不要这样做,它违背了条件运算符的目的:if true then true, if false then false
你猜怎么着?您可以完全删除它! value.to_s == 'true' ? true : false
应该只是 value.to_s == 'true'
@EricDuminil 绝对同意,当时的菜鸟错误。
请注意,当值无法转换时,此答案将返回 nil,而那些单行代码永远不会失败,并且始终返回 false,除非值为“真”。两者都是有效的方法,可能是不同情况的正确答案,但它们并不相同。
@AndreFigueiredo 在这种情况下,三元运算符不做任何事情。尝试不使用,然后比较结果。【参考方案2】:
h = "true"=>true, true=>true, "false"=>false, false=>false
["true", true, "false", false].map |e| h[e]
#=> [true, true, false, false]
【讨论】:
【参考方案3】:可以使用像https://rubygems.org/gems/to_bool 这样的gem,但可以使用正则表达式或三进制轻松地将它写在一行中。
正则表达式示例:
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
【讨论】:
注意:\A
/\z
是字符串的开始/结束,^
/$
是行的开始/结束。所以如果var == "true\nwhatevs"
那么boolean == true
。
这对我很有帮助,我非常喜欢var.eql?('true') ? true : false
。谢谢!
@Christian 记住它必须是 var.to_s.eql?不只是 var.eql?否则它不会将布尔值 true 转换为字符串 'true'【参考方案4】:
def true?(obj)
obj.to_s.downcase == "true"
end
【讨论】:
是的,@null,to_s 方法将布尔值 true 或 false 转换为“true”或“false”,如果最初是字符串,则保持值不变。现在我们确定将“true”或“false”作为字符串......我们只需要使用 == 检查字符串是否等于“true”。如果是,则原始值为真或“真”。如果不是,则原始值为 false、“false”或完全不相关的内容。 由于字符串可能被大写/标题,小写将确保匹配:obj.to_s.downcase == 'true'
使用downcase!
你会少分配1个对象。 downcase
将复制现有字符串。当 Frozen String Literals 成为 Ruby 默认选项时,这将不再那么重要。
我冒昧地编辑了答案以包含小写的建议!根据上述cmets。阅读起来不太优雅,但如果你不确定你正在使用什么变量类型,那么更健壮性永远不会坏。
如果您输入错误数据,这不会报告错误,因此如果您需要任何错误处理,这不是一个很好的解决方案【参考方案5】:
虽然我喜欢哈希方法(我过去曾将它用于类似的东西),但考虑到您只关心匹配真实值 - 因为 - 其他所有内容都是错误的 - 您可以检查是否包含在数组中:
value = [true, 'true'].include?(value)
或者如果其他值可以被认为是真实的:
value = [1, true, '1', 'true'].include?(value)
如果您原来的 value
可能是大小写混合,您将不得不做其他事情:
value = value.to_s.downcase == 'true'
但同样,对于您对问题的具体描述,您可以使用最后一个示例作为您的解决方案。
【讨论】:
【参考方案6】:在 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 对数据库相同的方式匹配布尔字符串比较,这很好。
【讨论】:
【参考方案7】:如果你使用 Rails 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 值 - 除非值是 nil 或匹配 false 值,否则假定为 true。两个版本中的 False 值相同:
FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"]
Rails 5 来源:https://github.com/rails/rails/blob/5-1-stable/activemodel/lib/active_model/type/boolean.rb
【讨论】:
这很有帮助,虽然我希望 Rails 中的FALSE_VALUES
集合也包含“no”。
@pjrebsch 在你的应用中打补丁相当简单。只需将 ActiveRecord::Type::Boolean::FALSE_VALUES << "no"
添加到初始化程序即可。
请注意,ActiveModel::Type::Boolean.new.cast(value)
区分大小写...所以 'False' 将与除 'false' 之外的任何其他字符串一样评估为 true。空字符串''
默认为 nil,而不是 false。 ^^@thomasfedb 提供的关于初始化程序定制的宝贵见解
ActiveModel::Type::Boolean.new.cast(nil)
也返回 nil
。
从 Rails 5.2.4 开始,@thomasfedb 建议的方法不再有效,因为 ActiveRecord::Type::Boolean::FALSE_VALUES
已冻结。【参考方案8】:
我经常使用这种模式来扩展 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
,它可以是:
您可以调用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
【讨论】:
't' 和 'f' 'T' 和 'F'、'y' 和 'n'、'Y' 和 'N' 呢? 这很好用,例如。 “买”是否以“b”开头?"buy"=~/b/ => 0
但("buy"=~/b/).to_boolean => false
【参考方案9】:
别想太多:
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”。
【讨论】:
nil.to_s == 'true' #false
@juliangonzalez:这是我在所有其他解释中遗漏的事实 - 谢谢。【参考方案10】:
在一个 rails 5.1 应用程序中,我使用这个基于 ActiveRecord::Type::Boolean
构建的核心扩展。当我从 JSON 字符串反序列化布尔值时,它对我来说非常有效。
https://api.rubyonrails.org/classes/ActiveModel/Type/Boolean.html
# app/lib/core_extensions/string.rb
module CoreExtensions
module String
def to_bool
ActiveRecord::Type::Boolean.new.deserialize(downcase.strip)
end
end
end
初始化核心扩展
# config/initializers/core_extensions.rb
String.include CoreExtensions::String
rspec
# spec/lib/core_extensions/string_spec.rb
describe CoreExtensions::String do
describe "#to_bool" do
%w[0 f F false FALSE False off OFF Off].each do |falsey_string|
it "converts #falsey_string to false" do
expect(falsey_string.to_bool).to eq(false)
end
end
end
end
【讨论】:
这是完美的。正是我想要的。【参考方案11】:我对此有一点小窍门。 JSON.parse('false')
将返回 false
和 JSON.parse('true')
将返回 true。但这不适用于JSON.parse(true || false)
。因此,如果您使用 JSON.parse(your_value.to_s)
之类的东西,它应该以一种简单但笨拙的方式实现您的目标。
【讨论】:
【参考方案12】:在 Rails 中,我更喜欢使用ActiveModel::Type::Boolean.new.cast(value)
,正如此处其他答案中提到的那样
但是当我编写普通的 Ruby 库时。然后我使用JSON.parse
(标准Ruby库)将字符串“true”转换为true
和“false”转换为false
的hack。例如:
require 'json'
azure_cli_response = `az group exists --name derrentest` # => "true\n"
JSON.parse(azure_cli_response) # => true
azure_cli_response = `az group exists --name derrentesttt` # => "false\n"
JSON.parse(azure_cli_response) # => false
来自实时应用的示例:
require 'json'
if JSON.parse(`az group exists --name derrentest`)
`az group create --name derrentest --location uksouth`
end
在 Ruby 2.5.1 下确认
【讨论】:
【参考方案13】:在 Rails 5 中工作
ActiveModel::Type::Boolean.new.cast('t') # => true
ActiveModel::Type::Boolean.new.cast('true') # => true
ActiveModel::Type::Boolean.new.cast(true) # => true
ActiveModel::Type::Boolean.new.cast('1') # => true
ActiveModel::Type::Boolean.new.cast('f') # => false
ActiveModel::Type::Boolean.new.cast('0') # => false
ActiveModel::Type::Boolean.new.cast('false') # => false
ActiveModel::Type::Boolean.new.cast(false) # => false
ActiveModel::Type::Boolean.new.cast(nil) # => nil
【讨论】:
ActiveModel::Type::Boolean.new.cast("False") # => true
... 在您的输入中使用 to_s.downcase 是个好主意
小心:ActiveModel::Type::Boolean.new.cast('fals') # => true
ActiveModel::Type::Boolean.new.cast('falso') # => true
【参考方案14】:
接近已经发布的内容,但没有多余的参数:
class String
def true?
self.to_s.downcase == "true"
end
end
用法:
do_stuff = "true"
if do_stuff.true?
#do stuff
end
【讨论】:
【参考方案15】:Rubocop 建议格式:
YOUR_VALUE.to_s.casecmp('true').zero?
https://www.rubydoc.info/gems/rubocop/0.42.0/RuboCop/Cop/Performance/Casecmp
【讨论】:
我喜欢这个答案,因为它是一个处理原始问题中陈述的所有情况的单行代码,包括“true”和“false”中的大写与小写 T 和 F。与正则表达式不同,它不会自行处理“T”或“F”。唯一的批评者是“零”的用法?不熟悉该方法的人可能会感到困惑。【参考方案16】:为简单起见,您可以使用eval
。
请小心并避免过度使用 eval,因为它很容易成为安全风险。
eval('false') # => false
eval('true') # => true
更多关于评估:https://apidock.com/ruby/Kernel/eval
【讨论】:
以上是关于Ruby:如何将字符串转换为布尔值的主要内容,如果未能解决你的问题,请参考以下文章
如何使用javascript将字符串数组转换为布尔值? [复制]