I need to check if given String includes a string or regex. If it does, it should return true, otherwise - false. How can I do it?
I have:
def method(string)
if #text.match(/#{string}/)
true
else
false
end
end
But I'm not sure if it's a proper way.
Consider this:
#text = 'foobar'
def method1(string)
if #text.match(/#{string}/)
true
else
false
end
end
That can be reduced to:
def method2(string_or_regex)
if #text[string_or_regex]
true
else
false
end
end
String's [] method allows us to pass in a string or a pattern. If it's a string, the method uses it for a fixed-string/in-string search. If a pattern is passed in it returns the matching text.
However, Ruby is more friendly than this. We don't have to tell it to return a true or false value conditionally. In Ruby, a nil or false value is treated as false, and anything else is "truethy". We can convert a value to true/false using !!, which is double boolean "not":
true # => true
'foo' # => "foo"
false # => false
nil # => nil
!true # => false
!'foo' # => false
!false # => true
!nil # => true
!!true # => true
!!'foo' # => true
!!false # => false
!!nil # => false
Knowing that, and that String's [] returns a nil if not found, or the matching text if found:
'foo'['foo'] # => "foo"
'foo'['bar'] # => nil
we can reduce the original method to:
def method3(string_or_regex)
!!#text[string_or_regex]
end
Here's what happens testing each of the methods above:
method1('foo') # => true
method1('baz') # => false
method2('foo') # => true
method2(/foo/) # => true
method2('baz') # => false
method2(/baz/) # => false
method3('foo') # => true
method3(/foo/) # => true
method3('baz') # => false
method3(/baz/) # => false
You have to be careful interpolating a regular expression object into another regular expression:
string = /foo/
/#{string/ # => /(?-mix:foo)/
The (?-mix: are the pattern flags being inserted inside another pattern, which can open your pattern to all sorts of weird behaviors and create extremely hard to find bugs. Instead, I strongly recommend using the source method if you're going to do that, which results in the original pattern being inserted:
/#{string.source}/ # => /foo/
Code with single line:
!#text.match(/#{string}/).nil?
Related
I have a string which is passed as a parameter to a function. Here, I want to check if the string contains only numbers. So I had a check like below:
def check_string(string)
result = false
if string.to_i.to_s.eql? string
result = true
end
result
end
But the problem arises when a string starts with 0. In that case, a false is returned.
check_string('123') #=> true
check_string('0123') #=> false
How can I solve this issue?
You can try the following
def check_string(string)
string.scan(/\D/).empty?
end
It would be truthy if string contains only digits or if it is an empty string. Otherwise returns false.
A number can be negative, or a float. So if these are allowed, consider this solution:
def is_numberic?(str)
str == "#{str.to_f}" || str == "#{str.to_i}"
end
some input which evaluate to true
pry(main)> is_numberic? '5'
=> true
pry(main)> is_numberic? '58127721'
=> true
pry(main)> is_numberic? '58127721.737673'
=> true
pry(main)> is_numberic? '0'
=> true
pry(main)> is_numberic? '1818'
=> true
pry(main)> is_numberic? '0.1'
=> true
pry(main)> is_numberic? '0.0'
=> true
pry(main)> is_numberic? '11.29'
=> true
pry(main)> is_numberic? '-0.12'
=> true
pry(main)> is_numberic? '-29'
=> true
the input which evaluate to false
pry(main)> is_numberic? '10 years'
=> false
pry(main)> is_numberic? '01'
=> false
pry(main)> is_numberic? '00'
=> false
pry(main)> is_numberic? '0.10'
=> false
pry(main)> is_numberic? ''
=> false
As you can see, there're several cases which probably should be supported, eg '0.10', but are not. In this case, the permitted input is '0.1'.
def check_string(str)
str !~ /\D/
end
check_string '123'
#=> true
check_string ''
#=> true
check_string '1a2'
#=> false
this is my proposition for detecting if it's a float number
def check(string)
scan = string.scan(/\D/)
scan.size == 0 || (scan.size == 1 && scan.first == ".") # or "," depend on your separator
end
example of use:
check("123") => true
check("12.3") => true
check("12e3") => false
check("12.3.2") => false
EDIT: 2023
After some years i see this is the most compact solution:
def check_string(str)
str.scan(/\D/).empty?
end
You can use Regexp for it:
def check_string(string)
raise 'Empty string passed' if string.empty?
/\A\d+\z/ === string
end
check_string '123'
#=> true
check_string '0123'
#=> true
check_string '0'
#=> true
We can also use the "match" function to do this.
"1234".match(/\D/)
#=> nil
"1234foo".match(/\D/)
#=> #<MatchData "f">
match (String) - APIdock
I think we should use the regex to find this.
it will work for the below scenarios
"3.0"
"av3"
"3"
is_numeric = false if option.option.match?(/[^0-9.]/)
If anyone is searching for another way to determine if string is numeric -> is to use "is_a? Numeric". Is_a? reference documentation
"namaste".is_a? Numeric
=> false
6.is_a? Numeric
=> true
str1 = "foo"
str2 = 9
str1.is_a? Numeric
=> false
str2.is_a? Numeric
=> true
You can also use:
7.is_a?(Numeric)
=> true
"too".is_a?(Numeric)
=> false
Basically it's determining if a class is a type of class object. I just found this and thought I would share.
This question already has answers here:
Why would you use a !! operator
(5 answers)
Closed 6 years ago.
What does !! mean in the following method?
def include?(record)
!!#association.include?(record)
end
It casts a variable into type boolean and determine its truthy or falsy value
For example:-
# Numbers...
!!1 # => true
!!0 # => true
# Numbers as strings...
!!'1' # => true
!!'0' # => false
# Truthy strings (case insensitive)...
!!'true' # => true (alias: 't')
!!'false' # => false (alias: 'f')
!!'yes' # => false (alias: 'y')
!!'no' # => false (alias: 'n')
# Booleans...
!!true # => true
!!false # => false
# Nil...
!!nil # => false
It helps you get boolean results.
For Example:
a = nil
!a
#=> true
!!a
#=> false
Similarly
a = 1
!a
#=> false
!!a
#=> true
The double exclamation mark will convert the result to a boolean value so that, in this case, if #assication.include?(record) returns nil that will get converted to false.
I'm running Ruby 2.2.1.
The following code runs as expected as string hash keys are duped and frozen:
f = 'foo'
h = {f => 'bar'}
h.compare_by_identity
h[f] # => nil
h['foo'] # => nil
h[h.keys.first] # => "bar"
But I can't for the life of me figure out what is going on here:
h = {'foo' => 'bar'}
h.compare_by_identity
h.keys.first.frozen? # => true
'foo'.frozen? # => false
h.keys.first.object_id # => 20421220
'foo'.object_id # => 20067280
h['foo'] # => "bar"
h['foo'.dup] # => nil
It's interesting to note the the docs for #compare_by_identity started using #dup at 2.2.0. So it seems this behavior change is known.
2.1.7:
h1["a"] #=> nil # different objects.
2.2.0:
h1["a".dup] #=> nil # different objects.
However, the source is the same.
The same does not happen with other literals like arrays. Any ideas on why this behavior changed for string literals? The docs give no hints as to why.
This is my code:
fred = {
'age' => 63,
'gender' => 'male',
'favorite painters' => ['Monet', 'Constable', 'Da Vinci']
}
fred.delete_if { |k,v| k.match(/[a]/) }
puts fred
The result shows {"gender"=>"male"}.
If I change the code to
fred.delete_if { |k,v| k.include?(/[a]/) }
it won't work.
Can anyone explain why to me?
String#match takes a regex object (or a regex pattern string) as the parameter while String#included? takes a string as the parameter.
You should use:
fred.delete_if { |k,v| k.include?('a') }
For more info, see the document.
.include? returns boolean true/false, and expects a string as input.
.match returns information about the match in the form of MatchData (or nil if nothing was matched), and accepts a string or regular expression.
Everyone is recommending using include? for a literal match. I prefer a different syntax that accomplishes the same thing:
"foo".include?("o") # => true
"foo"["o"] # => "o"
"foo".include?("a") # => false
"foo"["a"] # => nil
In Ruby, anything that is not nil or false is considered true, so, for boolean tests the above tests are equivalent if you get a value or true, or if you get false or nil.
If you absolutely must have a boolean result, use the !! ("not not") trick which nicely converts a "truthy" value to its boolean complement, then back to that value's boolean complement.
true # => true
false # => false
'a' # => "a"
nil # => nil
!true # => false
!false # => true
!'a' # => false
!nil # => true
!!true # => true
!!false # => false
!!'a' # => true
!!nil # => false
Which lets us do:
!!"foo"["o"] # => true
!!"foo"["a"] # => false
This results in more compact code, which might not be what your particular coding-style wants. It pushes the Ruby code toward Perl or C code so weigh the compactness with readability and pick which style you want.
See String#[] for more information.
What is the test function in the next Ruby expression:
unless ARGV.size == 1 and test(?e, ARGV[0])
test() seems to be reminiscent of the shell tests to see if files or directories exist, are readable, etc:
irb(main):011:0> test(?e,"/etc/passwd") # e for exist
=> true
irb(main):012:0> test(?e,"/does/not/exist")
=> false
irb(main):014:0> test(?e,"/etc")
=> true
irb(main):015:0> test(?d, "/etc") # d for directory
=> true
irb(main):016:0> test(?d, "/etc/passwd")
=> false
irb(main):017:0> test(?r, "/etc/passwd") # r for readable
=> true
irb(main):018:0> test(?w, "/etc/passwd") # w for writable
=> false
Full details are in the ri Kernel#test documentation.