Squeeze double char in Ruby - ruby

What is the best way to squeeze multicharacter in string ?
Example:
hahahahahaha => ha
lalalala => la
awdawdawdawd => awd
str.squeeze("ha") # doesn't work
str.tr("haha", "ha") # doesn't work

def squeeze(s)
s.gsub(/(.+?)\1+/, '\1')
end
puts squeeze('hahahaha') # => 'ha'
puts squeeze('awdawdawd') # => 'awd'
puts squeeze('hahahaha something else') # => 'ha something else'

You can use regex based search and replace:
str.gsub(/(ha)+/, 'ha')

Related

get the number from string by regex

I have a string like this:
"com.abcd.efghi.pay.0.99"
"com.abcd.efghi.pay.9.99"
"com.abcd.efghi.pay.19.99"
I want get the number(0.99, 9.99, 19.99). I tried to do like this:
"com.abcd.efghi.pay.0.99".scan(/\d/).join
=> "099"
Anyone can help me get the correct result. Thanks in advance!
"com.abcd.efghi.pay.0.99".split(/\D+/, 2).last # => "0.99"
"com.abcd.efghi.pay.9.99".split(/\D+/, 2).last # => "9.99"
"com.abcd.efghi.pay.19.99".split(/\D+/, 2).last # => "19.99"
or
"com.abcd.efghi.pay.0.99".sub(/\D+/, "") # => "0.99"
"com.abcd.efghi.pay.9.99".sub(/\D+/, "") # => "9.99"
"com.abcd.efghi.pay.19.99".sub(/\D+/, "") # => "19.99"
This is pretty simple, regexp for numbers like 0.00 or 00.00:
\d{1,2}.{2,}
\d Any digit
\d{1,2} Between 1 and 2 of digit
. a dot
\d{2,} 2 or more of digit
Example:
>> "com.abcd.efghi.pay.19.99"[/\d{1,2}.{2,}/, 0]
=> "19.99"
>> "com.abcd.efghi.pay.9.99"[/\d{1,2}.{2,}/, 0]
=> "9.99"
You probably want something like this:
\d+(\.\d+)?
which looks for an integer followed by an optional fractional part.
Something like this:
"com.abcd.efghi.pay.0.99".scan(/(\d+[.]\d+)/).flatten.first
# => "0.99"
Without regex:
str = "com.abcd.efghi.pay.0.99"
str.split(".").last(2).join(".") # => "0.99"
You can use this regex in scan:
\b\d+(?:\.\d+)?
You need to use end of the line anchor.
\b\d+(?:\.\d+)?$
Ah, so many ways. Here are a couple more:
str = "com.abcd.efghi.pay.9.99"
str[str.index(/\d/)..-1] #=> "9.99"
str.sub(/.*?(?=\d)/,'') #=> "9.99"

How to pass a regular expression as an argument to a function?

The following line of code correctly selects "Joe Bloggs" from a dropdown:
browser.select_list(:id => "ListOwnerID").option(:text => /Joe Bloggs/).select # edited: added '.select'
How do I pass the owner's name as the variable "list_owner"?
Something like:
def set_list_owner(list_owner)
browser.select_list(:id => "ListOwnerID").option(:text => /list_owner/).select
end
Usage:
set_list_owner("Joe Bloggs")
You can use Regexp::new:
re_string = '\d'
Regexp.new(re_string) =~ 'abc 123'
# => 4
Alternative Cary Swoveland suggested (regular expression interpolation):
/#{re_string}/
def set_list_owner(list_owner)
browser.select_list(:id => "ListOwnerID").option(:text => Regexp.new(list_owner))
end
set_list_owner("Joe Bloggs")
If you want to match the string literally, instead of interpreting as a regular expression, use Regexp::escape:
Regexp.new(Regexp.escape(list_owner))

How can I upcase first occurrence of an alphabet in alphanumeric string?

Is there any easy way to convert strings like 3500goat to 3500Goat and goat350rat to Goat350rat?
I am trying to convert the first occurrence of alphabet in an alphanumeric string to uppercase. I was trying the code below using the method sub, but no luck.
stringtomigrate = 3500goat
stringtomigrate.sub!(/\D{0,1}/) do |w|
w.capitalize
This should work:
string.sub(/[a-zA-Z]/) { |s| s.upcase }
or a shorthand:
string.sub(/[a-zA-Z]/, &:upcase)
examples:
'3500goat'.sub(/[a-zA-Z]/, &:upcase)
# => "3500Goat"
'goat350rat'.sub(/[a-zA-Z]/, &:upcase)
# => "Goat350rat"
Try this
1.9.3-p545 :060 > require 'active_support/core_ext'
=> true
1.9.3-p545 :099 > "goat350rat to Goat350rat".sub(/[a-zA-Z]/){ |x| x.titleize}
=> "Goat350rat to Goat350rat"

Obfuscating numbers in a string?

I have a challenge that calls for obfuscating numbers in a string, such as a SSN, for example: XXX-XX-4430. I've gotten pretty close:
def hide_all_ssns(string)
string.scan(/\w{3}-\w{2}-\w{4}/)
string.gsub('/\w{3}-\w{2}', 'XXX-XX')
end
but I get an error:
Error! hide_all_ssns obfuscates any SSNs in the string expected:
"XXX-XX-1422, XXX-XX-0744, XXX-XX-8762" got: "234-60-1422,
350-80-0744, 013-60-8762" (using ==)
I initially had the regular-expression (/\d{3}-\d{2}-\d{4}/) but thought that the problem was attempting to convert the integers in the string to X. Now I'm using \w, yet I am getting the same error.
Does anyone have any insight? I'm a newbie to coding and have exhausted Ruby-doc, as well as any blogs I can find on regex/gsub, but I am getting nowhere.
You're mis-using gsub (your regular expression needs to be between forward slashes), but I still thing gsub! is what you want...
def hide_all_ssns(string)
string.scan(/\w{3}-\w{2}-\w{4}/)
string.gsub!(/\w{3}-\w{2}/, 'XXX-XX')
end
Working example:
1.9.3p448 :063 > string = "123-45-6789"
=> "123-45-6789"
1.9.3p448 :064 > def hide_all_ssns(string)
1.9.3p448 :065?> string.scan(/\w{3}-\w{2}-\w{4}/)
1.9.3p448 :066?> string.gsub!(/\w{3}-\w{2}/, 'XXX-XX')
1.9.3p448 :067?> end
=> nil
1.9.3p448 :068 > hide_all_ssns(string)
=> "XXX-XX-6789"
1.9.3p448 :069 > string
=> "XXX-XX-6789"
Why does it have to be so hard? All U.S. social security numbers are the same format, right? So, work from that point. Here's some variations on a theme, ordered by escalating obscurity:
ssn = '123-45-6789' # => "123-45-6789"
ssn[0, 6] = 'XXX-XX' # => "XXX-XX"
ssn # => "XXX-XX-6789"
Or:
numbers = ssn.scan(/\d+/) # => ["123", "45", "6789"]
'XXX-XX-' + numbers.last # => "XXX-XX-6789"
Or:
ssn = '123-45-6789' # => "123-45-6789"
ssn[0, 6] = ssn[0, 6].gsub(/\d/, 'X') # => "XXX-XX"
ssn # => "XXX-XX-6789"
Or:
ssn[0,6] = ssn[0, 6].tr('0-9', 'X') # => "XXX-XX"
ssn # => "XXX-XX-6789"
Or:
numbers = ssn.split('-') # => ["123", "45", "6789"]
[*numbers[0, 2].map{ |s| 'X' * s.size }, numbers[-1]].join('-') # => "XXX-XX-6789"
Or:
ssn[/(\d+)-(\d+)-(\d+)/] # => "123-45-6789"
[$1, $2, $3] # => ["123", "45", "6789"]
[$3, *[$2, $1].map{ |s| s.gsub(/./, 'X') }].reverse.join('-') # => "XXX-XX-6789"
Of course, using one of these would cheating, since you're supposed to figure the challenge out by yourself, but they're good food for thought and a decent starting point for your own solution.
Short and simple... You could maybe try something like this:
crypted = ('X' * 6) + "4543-2329-1354-1111".to_s[14..18]
=> "XXXXXX-1111"

Regexp for finding href in <a> open-uri ruby

I need to find distance between two websites useing ruby open-uri. Using
def check(url)
site = open(url.base_url)
link = %r{^<([a])([^"]+)*([^>]+)*(?:>(.*)<\/\1>|\s+\/>)$}
site.each_line {|line| puts $&,$1,$2,$3,$4 if (line=~link)}
p url.links
end
Finding links not working properly. Any ideas why ?
If you want to find the a tags' href parameters, use the right tool, which isn't often a regex. More likely you should use a HTML/XML parser.
Nokogiri is the parser of choice with Ruby:
require 'nokogiri'
require 'open-uri'
doc = Nokogiri.HTML(open('http://www.example.org/index.html'))
doc.search('a').map{ |a| a['href'] }
pp doc.search('a').map{ |a| a['href'] }
# => [
# => "/",
# => "/domains/",
# => "/numbers/",
# => "/protocols/",
# => "/about/",
# => "/go/rfc2606",
# => "/about/",
# => "/about/presentations/",
# => "/about/performance/",
# => "/reports/",
# => "/domains/",
# => "/domains/root/",
# => "/domains/int/",
# => "/domains/arpa/",
# => "/domains/idn-tables/",
# => "/protocols/",
# => "/numbers/",
# => "/abuse/",
# => "http://www.icann.org/",
# => "mailto:iana#iana.org?subject=General%20website%20feedback"
# => ]
I see several issues with this regular expression:
It is not necessarily the case that a space must come before the trailing slash in an empty tag, yet your regexp requires it
Your regexp is very verbose and redundant
Try the following instead, it will extract you the URL out of <a> tags:
link = /<a \s # Start of tag
[^>]* # Some whitespace, other attributes, ...
href=" # Start of URL
([^"]*) # The URL, everything up to the closing quote
" # The closing quotes
/x # We stop here, as regular expressions wouldn't be able to
# correctly match nested tags anyway

Resources