Ruby : 문자열을 부울로 변환하는 방법


107

boolean true, boolean false, 문자열 "true"또는 문자열 "false"중 하나가 될 값이 있습니다. 문자열이면 부울로 변환하고, 그렇지 않으면 수정하지 않은 상태로 둡니다. 다시 말해:

"true"는 true가되어야합니다.

"false"는 false가되어야합니다.

사실은 사실이어야한다

거짓은 거짓이어야한다


2
결과는 않는 두 값 중 하나가 될 true또는 false결과가 truthy 또는 falsey 경우 또는 충분하다? 후자의 경우, falsefalsey 이미, 모두 true와는 'true'결과가 이미 정확하지되는 유일한 값이 있으므로, truthy 있습니다 'false': if input == 'false' then true else input end그것을해야한다.
Jörg W Mittag

Jorg는 훌륭한 의견이지만 일부 응용 프로그램의 경우 진실 또는 거짓 값이 아니라 부울 값이 참 또는 거짓이어야한다고 가정합니다.
emery

2
Emery, 부울을 반환해야하는 경우 @ Jörg의 표현식 앞에 두 개의 "nots"를 추가 할 수 !!(if input == 'false' then true else input end)있습니다.. 두 번째 !는 반환 값을 원하는 것과 반대되는 부울로 변환합니다. 첫 번째 !가 수정합니다. 이 "속임수"는 오래 전부터있었습니다. 모든 사람이 그것을 좋아하지는 않습니다.
캐리 Swoveland

답변:


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

3
예, @null입니다. to_s 메소드는 부울 true 또는 false를 "true"또는 "false"로 변환하고 원래 문자열 인 경우 값을 변경하지 않습니다. 이제 문자열로 "true"또는 "false"가 있는지 확인하고 문자열이 "true"인지 확인하기 위해 ==를 사용해야합니다. 그렇다면 원래 값은 true 또는 "true"입니다. 그렇지 않은 경우 원래 값은 거짓, "거짓"또는 완전히 관련이없는 것입니다.
emery

8
문자열이 대문자 / 제목이 될 수 있으므로 아래로 대소 문자를 구분하면 다음과 같이 일치합니다.obj.to_s.downcase == 'true'
TDH

1
사용 downcase!하면 개체를 1 개 적게 할당합니다. downcase기존 문자열을 복제합니다. Frozen String Literals가 Ruby 기본 옵션이 될 때이 문제는 덜 중요합니다.
danielricecodes 18:49에

나는 다운 케이스의 제안을 포함하도록 대답을 편집 할 자유를 얻었습니다! 위의 의견에 따라. 읽는 것은 덜 우아하지만 어떤 변수 유형을 사용하고 있는지 확실하지 않으면 더 견고 함이 나쁘지 않습니다.
emery 19

당신이 그것을 잘못된 데이터를 공급하는 경우 어떤 오류 처리해야하는 경우가 좋은 해결책이 아니다 그래서 이것은 오류를보고 실 거예요
토비 1 케노비

118

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에서는 거짓 값만 검사합니다. 값이 nil이거나 거짓 값과 일치하지 않는 한 참으로 간주됩니다. 거짓 값은 두 버전에서 동일합니다. 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


1
이것은 도움이되지만 FALSE_VALUESRails 의 세트 에도 "no"가 포함 되기를 바랍니다 .
pjrebsch

3
@pjrebsch 앱에서 패치하기가 상당히 간단합니다. ActiveRecord::Type::Boolean::FALSE_VALUES << "no"이니셜 라이저에 추가 하기 만하면 됩니다.
thomasfedb

참고 ActiveModel::Type::Boolean.new.cast(value)바와 같이 대소 문자를 구별는 ... 그래서 '거짓'true로 평가합니다 '거짓'을 제외한 다른 문자열입니다. 빈 문자열의 ''기본값은 false가 아니라 nil입니다. ^^ 귀중한 통찰력 초기화 정의에 @thomasfedb가 여기에 제공된
frostini

1
ActiveModel::Type::Boolean.new.cast(nil)또한를 반환합니다 nil.
Nikolay D

1
Rails 5.2.4부터 @thomasfedb가 제안한 방법은 더 이상 작동하지 않습니다 ActiveRecord::Type::Boolean::FALSE_VALUES.
moveson

24

이 패턴을 자주 사용하여 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은 거짓, 나머지는 모두 참)
  • 참 부울 (true / false)
  • 문자열 ( "true", "false", "0", "1", "TRUE", "FALSE")

여러 조건문을 사용하는 대신 호출 만하면 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'은 어떻습니까?
MrMesees

이것은 너무 잘 작동합니다. "buy"가 "b"로 시작합니까? "buy"=~/b/ => 0 하지만("buy"=~/b/).to_boolean => false
Marcos

23

너무 많이 생각하지 마십시오.

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"를 추가 할 수도 있습니다.


5
nil.to_s == 'true' #false
juliangonzalez

15
if value.to_s == 'true'
  true
elsif value.to_s == 'false'
  false
end

10
한 - 라이너와 같은 코드value.to_s == 'true' ? true : false
사가르 디야

20
@ sagarpandya82을 : : 즉, 그것은 조건 연산자의 목적 패배 할 절대로 if true then true, if false then false무엇을 추측? 완전히 제거 할 수 있습니다! value.to_s == 'true' ? true : false그냥 있어야합니다value.to_s == 'true'
Eric

4
@EricDuminil은 당시 신인 오류에 절대적으로 동의합니다.
Sagar Pandya

2
이 답변은 값을 변환 할 수 없을 때 nil을 반환하는 반면 해당 one-liner는 실패하지 않으며 값이 'true'가 아니면 항상 false를 반환합니다. 둘 다 유효한 접근 방식이며 다른 상황에 대한 정답 일 수 있지만 동일하지는 않습니다.
Doodad

1
@AndreFigueiredo 삼항 연산자는이 경우 아무 작업도하지 않습니다. 없이 시도하고 결과를 비교하십시오.
Eric Duminil

13
h = { "true"=>true, true=>true, "false"=>false, false=>false }

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

7

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

이것은 완벽 해요. 내가 찾던 바로 그것.
Doug

5

Rails에서는 ActiveModel::Type::Boolean.new.cast(value) 여기에 다른 답변에서 언급 한 것처럼 합니다.

하지만 일반 Ruby lib를 작성할 때. 그런 다음 JSON.parse(표준 Ruby 라이브러리) 문자열 "true"를 true"false" 로 변환 하는 해킹을 사용합니다 false. 예 :

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에서 확인


5

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

1
ActiveModel::Type::Boolean.new.cast("False") # => true... 입력에 to_s.downcase를 사용하는 것이 좋습니다.
Raphayol

4

이것에 대한 약간의 해킹이 있습니다. JSON.parse('false')반환 false되고 JSON.parse('true')true를 반환합니다. 그러나 이것은 JSON.parse(true || false). 따라서 이와 같은 JSON.parse(your_value.to_s)것을 사용 하면 간단하지만 해키 방식으로 목표를 달성해야합니다.


3

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

2
참고 : \A/ \z 는 문자열의 시작 / 끝이고 ^/ $는 줄의 시작 / 끝입니다. 그렇다면 var == "true\nwhatevs"다음 boolean == true.
cremno

이것은 정말 저를 도왔고 저는 var.eql?('true') ? true : false매우 좋아했습니다 . 감사!
Christian

3

나는 해시 접근 방식을 좋아하지만 (과거에 비슷한 것들을 위해 사용했습니다) 진실한 값을 일치시키는 데에만 관심이 있다는 점을 감안할 때-다른 모든 것은 거짓이기 때문에-배열에 포함되는지 확인할 수 있습니다.

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

또는 다른 값이 진실이라고 간주 될 수있는 경우 :

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

원본 value이 대소 문자가 혼합 된 경우 다른 작업을 수행해야합니다 .

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

그러나 다시 말하지만, 문제에 대한 구체적인 설명을 위해 마지막 예제를 솔루션으로 사용할 수 있습니다.


2

레일에서 이전에 다음과 같은 작업을 수행했습니다.

class ApplicationController < ActionController::Base
  # ...

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

  # ...
end

레일스가 데이터베이스에서하는 것과 같은 방식으로 부울 문자열 비교를 일치시키려는 경우에 좋습니다.


0

이미 게시 된 항목에 가깝지만 중복 매개 변수가 없습니다.

class String
    def true?
        self.to_s.downcase == "true"
    end
end

용법:

do_stuff = "true"

if do_stuff.true?
    #do stuff
end
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.