Check if a string contains only digits in ruby - ruby

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.

Related

Ruby Method not Returning False within a Recursion Block

I'm doing a ruby challenge that I found on rubeque.com. Here are the instructions:
Instructions:
Write a method #r_empty? that returns true if a hash and its subhashes are empty or false if there is a value in the hash.
My Answer:
class Hash
def r_empty?
def recurse(h)
h.each {|key, value|
value.is_a?(Hash) ? recurse(value) :
if (value!=nil && value!="")
#puts value
return false
end
}
return true
end
recurse(self)
end
end
Test:
a = {:ruby => "", :queue => ""}
b = {:ruby => {:version => {:one => {"nine" => ""}, "two" => "=^.^="}},
:html => ""}
c = {:pets => {:dogs => {:my => {"niko" => ""}, "ollie" => ""}}, :cats =>
nil, :mice => ""}
d = {a: "", b: :two, c: ""}
Answers:
a.r_empty?, true
b.r_empty?, false
c.r_empty?, true
d.r_empty?, false
({}.r_empty?), true
Using this code, I was able to get the right answer for 4 out of the 5 tests. My method returns TRUE for b.r_empty? ... I do notice that if I uncomment out #puts value, "=^.^=" is printed out for b.r_empty? ... So the if statement is being executed, but ultimately false is not returned. I'm still a ruby novice so I will gladly appreciate any advice and guidance towards the right topics i should go over for this challenge.
Although it's cool to define a method inside another (I did not know this was possibly actually) the method can be simplified quite a bit:
class Hash
def r_empty?
!values.any? do |val|
val.is_a?(Hash) ? !val.r_empty? : (val && val != "")
end
end
end
I'm not sure exactly the problem is with your original code, however I think the recurse(value) is effectively being discarded.
By the way, in terms of style I recommend only using a ternary for single-line expressions and also being diligent about consistent indentation.

!! (double bang) meaning in Ruby [duplicate]

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.

String includes another string or regex (Ruby)

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?

What is the difference between "include?" and "match"?

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.

Seeing if values of a hash are the same

I have a hash, whose values are true or false. What is the most Ruby-esque way to see if all the values of a given sub-hash of this hash are the same?
h[:a] = true
h[:b] = true
h[:c] = true
h[:d] = false
[h[:a], h[:b], h[:c]].include? false
[h[:a], h[:b], h[:c]].include? true
Is there a better way to write this?
values_at is the method to get a collection of values out of a Hash:
h.values_at(:a,:b,:c).all? #are they all true?
h.values_at(:a,:b,:c).any? #is at least one of them true?
h.values_at(:a,:b,:c).none? #are they all false?
If all you want to do is evaluate they are ALL true or they are ALL false:
h[:a] && h[:b] && h[:c] && h[:d] # => false
!(h[:a] || h[:b] || h[:c] || h[:d]) # => false
h[:a] && h[:b] && h[:c] # => true
!h[:d] # => true
Otherwise, as Dave Newton pointed out, you can use the #all?, #any? and #none? methods.
> [h[:a], h[:b], h[:c]].all?
=> true
> [h[:a], h[:b], h[:d]].all?
=> false
> [h[:a], h[:b], h[:d]].all?
=> false
> [h[:d]].none?
=> true
all?, none?
Depending on your needs it might be cleaner to write something like:
> [:a, :b, :c].all? { |key| h[key] }
=> true
> [:a, :b, :d].all? { |key| h[key] }
=> false
> [:a, :d].none? { |key| h[key] }
=> false
> [:d].none? { |key| h[key] }
=> true
Another general-purpose method:
whatever.uniq.size == 1
This tests directly whether all the values in whatever are the same. So, in your case,
h.values_at(:a, :b, :c).uniq.size == 1

Resources