How to determine if a string is a number? - ruby-on-rails

What is the easiest way to find out in Rails 3 whether a string str contains a positive float number or not ? (str is not an attribute in an active-record model)
It should work like this:
str = "123" => true
str = "123.456" => true
str = "0" => true
str = "" => false
str = "abcd" => false
str = "-123" => false

Here's one idea:
class String
def nonnegative_float?
Float(self) >= 0
rescue ArgumentError
return false
end
end
However, since you already seem to have a pretty good idea of what a nonnegative float number looks like, you could also match it against a Regexp:
class String
def nonnegative_float?
!!match(/\A\+?\d+(?:\.\d+)?\Z/)
end
end

You can match it against a regular expression.
str === /^\d+(\.\d+)?$/

Related

Ruby: Get the value if end_with? is true

Looking for a clean way to return the characters of a string if end_with? evaluates to true.
i.e.
s = "my_name"
name = s.end_with?("name")
puts name
>> "name"
My use case would look somewhat like this:
file_name = "some_pdf"
permitted_file_types = %w(image pdf)
file_type = file_name.end_with?(*permitted_file_types)
puts file_type
>> "pdf"
I would do this:
"my_name".scan(/name\z/)[0]
#=> "name"
"something".scan(/name\z/)[0]
#=> nil
May be using match and \z (end of string)?
string = "my_name"
suffix1 = "name"
suffix2 = "name2"
In Ruby >= 3.1
result1 = %r{#{suffix1}\z}.match(string)&.match(0)
# => "name"
result2 = %r{#{suffix2}\z}.match(string)&.match(0)
# => nil
In Ruby < 3.1
result1 = %r{#{suffix1}\z}.match(string)&.[](0)
# => "name"
result2 = %r{#{suffix2}\z}.match(string)&.[](0)
# => nil
Just for fun trick with tap:
string.tap { |s| break s.end_with?(suffix1) ? suffix1 : nil }
# => "name"
string.tap { |s| break s.end_with?(suffix2) ? suffix2 : nil }
# => nil
ruby already has a String#end_with? method, going back to at least version 2.7.1, maybe earlier. But it returns a boolean and you want the matched string to be returned. You're calling a method on an instance of String, so you're apparently wanting to add a method to the String class.
class String #yeah we're monkey patching!
def ends_with?(str) #don't use end_with.. it's already defined
return str if self.end_with?(str)
end
end
#now
s="my_name"
s.ends_with?("name") #=> "name"
But I really wouldn't bother with all that... I'd just work with what Ruby provides:
s = "my_name"
str = "name"
result = str if s.end_with?(str)

Remove characters after any tags

I am working in rails. I have one doubt.
1. a = "ABCD123"
I want to print ABCD123
2. b = "ABCDE<123>"
I want to print ABCDE
For that I am using this
a.scan(/\b[A-Za-z]+\b/).join and
b.scan(/\b[A-Za-z]+\b/).join.
First one is giving nil but I want to print it as ABCD123 and second one is showing correct what I want.
Could anyone please help me. Thanks.
code below can remove all tags in the string
a = "ABCD123"
b = "ABCDE<123>"
a.gsub /<.*?>/, '' # => "ABCD123"
b.gsub /<.*?>/, '' # => "ABCDE"
def conversion(str)
index_number = str.index(/[\W_]+/)
if index_number.present?
main_str = str.gsub(str[index_number..],'')
else
main_str = str
end
return main_str
end
or you can use
b = "ABCD-123"
b.match(/(^[A-Za-z0-9]+)/)[1]
#=> "ABCD"
You can try following,
b = "ABCDE<123>"
b[/[^<>]+/]
# => "ABCDE"
Since comments are a bit limited:
Here is a small snippet to test different inputs.
strings = %w[ABCD123 ABCD<123> ABCD <123>ABCDE]
strings.each do |string|
match = string.match(/(^[A-Za-z0-9]+)/)
if match
puts "'#{string}' => #{match[1]}"
else
puts "'#{string}' does not match pattern"
end
end
Is this the desired behaviour?
'ABCD123' => ABCD123
'ABCD<123>' => ABCD
'ABCD' => ABCD
'<123>ABCDE' does not match pattern

Why to_json returned a String not equal with the same json String

In Rails console
> h_json = {key: "value"}.to_json;
#=> "{\"key\":\"value\"}"
> s_json = %Q|{"key": "value"}|
#=> "{\"key\": \"value\"}"
> s_json.class
#=> String
> h_json.class
#=> String
We can see both h_json and s_json have the same String class, and looks the same, however
#=> "{\"key\": \"value\"}"
> s_json == h_json
#=> false
They don't equals each other, I don't understand why.
there is a space in the s_json, if you checked the source code of the to_json function
# File activesupport/lib/active_support/json/encoders/hash.rb, line 33
def to_json(options = nil) #:nodoc:
hash = as_json(options)
result = '{'
result << hash.map do |key, value|
"#{ActiveSupport::JSON.encode(key.to_s)}:#{ActiveSupport::JSON.encode(value, options)}"
end * ','
result << '}'
end
this function doesn't add a space between the colon : and the value.
So actually,
h_json = "{\"key\":\"value\"}"
and
s_json = "{\"key\": \"value\"}"
if you set s_json = "{\"key\":\"value\"}" they must be equal.

Replace until all occurrences are removed

I have the following strings:
",||||||||||||||"
",|||||a|||||,|"
I would like to achieve that all occurrences of ",|" are replaced with ",,"
The output should be the following:
",,,,,,,,,,,,,,,"
",,,,,,a|||||,,"
When I run .gsub(',|', ',,') on the strings I get not the desired output.
",,|||||||||||||"
",,||||a|||||,,"
That's because it does not run gsub several times.
Is there a similar method that runs recursively.
A regular expression matches can not overlap. Since matches are what is used for replacement, you can't do it that way. Here's two workarounds:
str = ",|||||a|||||,|"
while str.gsub!(/,\|/, ',,'); end
str = ",|||||a|||||,|"
str.gsub!(/,(\|+)/) { "," * ($1.length + 1) }
smoke_weed_every_day = lambda do |piper|
commatosed = piper.gsub(',|', ',,')
commatosed == piper ? piper : smoke_weed_every_day.(commatosed)
end
smoke_weed_every_day.(",||||||||||||||") # => ",,,,,,,,,,,,,,,"
smoke_weed_every_day.(",|||||a|||||,|") # => ",,,,,,a|||||,,"
From an old library of mine. This method iterates until the block output is equal to its input :
def loop_until_convergence(x)
x = yield(previous = x) until previous == x
x
end
puts loop_until_convergence(',||||||||||||||') { |s| s.gsub(',|', ',,') }
# ",,,,,,,,,,,,,,,"
puts loop_until_convergence(',|||||a|||||,|') { |s| s.gsub(',|', ',,') }
# ",,,,,,a|||||,,"
As a bonus, you can calculate a square root in very few iterations :
def root(n)
loop_until_convergence(1) { |x| 0.5 * (x + n / x) }
end
p root(2)
# 1.414213562373095
p root(3)
# 1.7320508075688772
As with #Amandan's second solution there is no need to iterate until no further changes are made.
COMMA = ','
PIPE = '|'
def replace_pipes_after_comma(str)
run = false
str.gsub(/./) do |s|
case s
when PIPE
run ? COMMA : PIPE
when COMMA
run = true
COMMA
else
run = false
s
end
end
end
replace_pipes_after_comma ",||||||||||||||"
#=> ",,,,,,,,,,,,,,,"
replace_pipes_after_comma ",|||||a|||||,|"
#=> ",,,,,,a|||||,,"

Ruby way to Check for string palindrome

I wanted to check if a string is palindrome or not using ruby code.
I am a starter in ruby so not too aquainted with the string methods in ruby
If you are not acquainted with Ruby's String methods, you should have a look at the documentation, it's very good. Mithun's answer already showed you the basic principle, but since you are new to Ruby, there's a couple more things to keep in mind:
*) If you have a predicate method, it's customary to name it with a trailing question mark, e.g. palindrome?.
*) Boolean expressions evaluate to a boolean, so you don't need to explicitly return true or false. Hence a short idiomatic version would be
def palindrome?(str)
str == str.reverse
end
*) Since Ruby's classes are open, you could add this to the string class:
class String
def palindrome?
self == self.reverse
end
end
*) If you don't want to monkey-patch String, you can directly define the method on single object (or use a module and Object#extend):
foo = "racecar"
def foo.palindrome?
self == self.reverse
end
*) You might want to make the palindrome check a bit more complex, e.g. when it comes to case or whitespace, so you are also able to detect palindromic sentences, capitalized words like "Racecar" etc.
pal = "Never a foot too far, even."
class String
def palindrome?
letters = self.downcase.scan(/\w/)
letters == letters.reverse
end
end
pal.palindrome? #=> true
def check_palindromic(variable)
if variable.reverse == variable #Check if string same when reversed
puts "#{ variable } is a palindrome."
else # If string is not the same when reversed
puts "#{ variable } is not a palindrome."
end
end
The recursive solution shows how strings can be indexed in Ruby:
def palindrome?(string)
if string.length == 1 || string.length == 0
true
else
if string[0] == string[-1]
palindrome?(string[1..-2])
else
false
end
end
end
If reading the Ruby string documentation is too boring for you, try playing around with the Ruby practice questions on CodeQuizzes and you will pick up most of the important methods.
def is_palindrome(value)
value.downcase!
# Reverse the string
reversed = ""
count = value.length
while count > 0
count -= 1
reversed += value[count]
end
# Instead of writing codes for reverse string
# we can also use reverse ruby method
# something like this value == value.reverse
if value == reversed
return "#{value} is a palindrom"
else
return "#{value} is not a palindrom"
end
end
puts "Enter a Word"
a = gets.chomp
p is_palindrome(a)
class String
def palindrome?
self.downcase == self.reverse.downcase
end
end
puts "racecar".palindrome? # true
puts "Racecar".palindrome? # true
puts "mississippi".palindrome? # false
str= gets.chomp
str_rev=""
n=1
while str.length >=n
str_rev+=str[-n]
n+=1
end
if str_rev==str
puts "YES"
else
puts "NO"
end
> first method
a= "malayalam"
if a == a.reverse
puts "a is true"
else
puts "false"
end
> second one
a= "malayalam"
a=a.split("")
i=0
ans=[]
a.count.times do
i=i+1
k=a[-(i)]
ans << k
end
if a== ans
puts "true"
else
puts "false"
end
def palindrome?(string)
string[0] == string[-1] && (string.length <= 2 || palindrome?(string[1..-2]))
end
**Solution 1** Time complexity = O(n), Space complexity = O(n)
This solution does not use the reverse method of the String class. It uses a stack(we could use an array that only allows entry and exit of elements from one end to mimic a stack).
def is_palindrome(str)
stack = []
reversed_str = ''
str.each_char do |char|
stack << char
end
until stack.empty?
reversed_str += stack.pop
end
if reversed_str == str
return true
else
return false
end
end
` Solution 2: Time complexity = O(n), Space complexity = O(1)
def inplace_reversal!(str)
i =0
j = str.length - 1
while i < j
temp = str[i]
str[i] = str[j]
str[j] = temp
i+=1
j-=1
end
return str
end
def palindrome?(str)
return "Please pass the string" if str.nil?
str = str.downcase
str_array = str.split('')
reverse_string = str_array.each_index{ |index| str_array[str_array.count - index - 1 ] end
return ("String #{str} is not a palindrome") unless str == reverse_string.join('')
"String #{str} is palindrome"
end

Resources