In a Rails app I am reading a file with key/values. An index number is embedded in the key name, and I'd like to remove it, along with one of the spacing underscores.
So in the sample data below, I'd like to convert:
PRIMER_LEFT_1_END_STABILITY into PRIMER_LEFT_END_STABILITY
PRIMER_RIGHT_1_END_STABILITY into PRIMER_RIGHT_END_STABILITY
PRIMER_PAIR_1_COMPL_ANY_TH into PRIMER_PAIR_COMPL_ANY_TH
Sample Data
PRIMER_LEFT_1_END_STABILITY=7.2000
PRIMER_RIGHT_1_END_STABILITY=7.9000
PRIMER_PAIR_1_COMPL_ANY_TH=0.00
EDIT
Thanks to #tihom for the first answer. It's partially working, but I did not specify that the embedded integer can be of any value. When over 1 digit in length the regex fails:
1.9.3-p327 :003 > "PRIMER_LEFT_221_END_STABILITY".sub(/_\d/,"")
=> "PRIMER_LEFT21_END_STABILITY"
1.9.3-p327 :004 > "PRIMER_LEFT_21_END_STABILITY".sub(/_\d/,"")
=> "PRIMER_LEFT1_END_STABILITY"
To remove the first occurrence use sub else to remove all occurrences use gsub
"PRIMER_LEFT_1_END_STABILITY".sub(/_(\d)+/,"") # => "PRIMER_LEFT_END_STABILITY"
"+" matches one or more of the preceding character. So in this case it matches one or more of any digit followed by a "_"
You can use String#tr and String#squeezeas below :
ar=['PRIMER_LEFT_1_END_STABILITY','PRIMER_RIGHT_1_END_STABILITY','PRIMER_PAIR_1_COMPL_ANY_TH']
p ar.map{|s| s.tr('0-9','').squeeze("_")}
# => ["PRIMER_LEFT_END_STABILITY", "PRIMER_RIGHT_-END_STABILITY", "PRIMER_PAIR_COMPL_ANY_TH"]
ar=["PRIMER_LEFT_221_END_STABILITY","PRIMER_LEFT_21_END_STABILITY"]
p ar.map{|s| s.tr('0-9','').squeeze("_")}
# => ["PRIMER_LEFT_END_STABILITY", "PRIMER_LEFT_END_STABILITY"]
Related
I'm building a profanity search function which needs to find instances of an array of profane words in a long string of text.
One could do a simple include like:
if profane_words.any? {|word| self.name.downcase.include? word}
...
end
This results in a positive match if ANY of the array of profane words are present anywhere in the text.
However, if a word like 'hell' is considered profane, this would produce a positive match against "Hell's Angels" or "Hell's Kitchen", which is undesirable.
How can the above search be modified to only produce positive results against distinct words or phrases? For example, "Hell Angels" returns positive but "Hell's Angels" returns negative.
To be clear, this means we're searching for any instance of a profane word that is immediately preceded or followed by another character or apostrophe.
What about using a regex ?
profane_words.any? { |word| self.name.downcase.match? /#{word}(?!')/ }
Examples:
"hell's angels".match?(/hell(?!')/) # => false
"hell angel".match?(/hell(?!')/) # => true
(?!') is a negative lookup meaning it won't match if the word has a ' right after it. If you'd like to exclude other characters you can add it to the list with pipes e.g. (?!'|") won't match ' and ".
See https://www.regular-expressions.info/lookaround.html for reference.
And you could make it more performant like this:
self.name.downcase.match? /#{profane_words.join('|')}(?!')/
if profane_words.any? {|word| self.name.downcase.split(' ').include? word} ... end
You should definitely use a Regex containing all your profane words followed by a space or period. Bellow yo
> "Hell's angels".match(/(hell|shit)[ .]/i)
=> nil
> "Hell angels".match(/(hell|shit)[ .]/i)
=> #<MatchData "Hell " 1:"Hell">
> "Hell's angels shit".match(/(hell|shit)[ .]/i)
=> nil
I need to match a url path with that contain any of 2 words vendor_tracks or shop_types, but shop types should be followed by a ' / '
My current REGEX is
//(vendor_tracks|shop_types)/
, but this match if contain shop_types/22
I need my Regex to match something like :
/shop_types?q%5Btrack_department
but NOT the below url
/shop_types/27/list_pinned_vendors
My current accepts both, while I need it to accept only the first. I tried many different methods to exclude the "shop_types" followed by / but always get escaped backslash error. Any solution for this? or alternative REGEX
You can use lookarounds to create custom restrictions
>> str1 = '/shop_types?q%5Btrack_department'
=> "/shop_types?q%5Btrack_department"
>> str2 = '/shop_types/27/list_pinned_vendors'
=> "/shop_types/27/list_pinned_vendors"
>> str1.match?(/shop_types(?!\/)/)
=> true
>> str2.match?(/shop_types(?!\/)/)
=> false
Here (?!\/) is negative lookahead which says that / character cannot be immediate character after shop_types
Note that end of string will also satisfy this condition as that would imply that there is no / character after shop_types
I tried many different methods to exclude the "shop_types" followed by / but always get escaped backslash error
You can use %r to define a regexp with alternate delimiters
# here the condition has also been changed
# restriction is that / shouldn't occur anywhere after matching shop_types
>> str1.match?(%r{shop_types(?!.*/)})
=> true
>> str2.match?(%r{shop_types(?!.*/)})
=> false
I get the following currencies in an import process:
$22.21
($55.95)
I can do Money.parse('$22.21') to parse into a RubyMoney object.
However, how can I parse ($55.95) into a negative RubyMoney object? Do I need to parse it to a negative number first and then into RubyMoney object? It seems like a common request but I can't find anything via search for some odd reason.
If I get -$55.95, I can then run Money.parse('-$55.95') on it. Bonus points if the method can handle both positive and negative currencies.
from the page that #swapnilabnave linked to:
:negative_format - Sets the format for negative numbers (defaults to prepending an hyphen to the formatted number given by :format). Accepts the same fields than :format, except %n is here the absolute value of the number.
So you would use (%u%n) for the desired effect.
You could do a regex to see if the string includes parenthesis. If it does, remove them, and prepend a negative sign:
str.include?(")") ? str.gsub(/\(|\)/, "").insert(0, "-") : str
Examples:
2.0.0p247 :013 > str = "($55.95)"
=> "($55.95)"
2.0.0p247 :014 > str.include?(")") ? str.gsub(/\(|\)/, "").insert(0, "-") : str
=> "-$55.95"
This works with positive values as well:
2.0.0p247 :016 > str = "$55.95"
=> "$55.95"
2.0.0p247 :017 > str.include?(")") ? str.gsub(/\(|\)/, "").insert(0, "-") : str
=> "$55.95"
First you can delete the parenthesis and then parse
money = "($55.95)"
money = money.delete!('()') and "-#{money}" or money
Money.parse(money)
It's in the readme of RubyMoney sign_before_symbol
Why don't you use number_to_currency ?
In my rails app i need to format my string so that it consist only letters, without symbols. But main trouble is that string is in russian language, so how do it? For rnglish and letters and digits i do that:
ArtLookup.get_analog(#articles.ART_ARTICLE_NR.gsub(/[^0-9A-Za-z]/, ''))
But how to do it for russian alphabet? (first is А, last is Я). Only letters, and delete spaces?
Use \p{Cyrillic}, which matches any cyrillic character.
Example:
1.9.3p194 :001 > s = "helloЯ"
=> "helloЯ"
1.9.3p194 :002 > s.gsub(/\p{Cyrillic}/, '')
=> "hello"
More info on special characters handling in Ruby: http://ruby-doc.org/core-1.9.3/Regexp.html
Edited Answer:
If you want only a subset of the cyrillic alphabet, I'm afraid you have to build your own set.
For this, you can try to use a range: /[а-я]+/i, which should work. If it doesn't, just specify your alphabet explicitely: /[абвгдеёжзийклмнопрстуфхцчшщъыьэюя]+/i
Is it possible to detect the last character of string in ruby on rails and replace it by "".
Explanation :: Suppose I have string as "demo-" then i have to check its last character, If it is "-" then replace it by "", otherwise no action should be taken.
Example - Code ::
search_text.downcase! if !search_text.nil?
now if seach_text have value as "demo-" then change it to "demo" by replacing "-".
Thanks in Advance !!!
Much simpler:
text.chomp!('-')
chomp already includes the if condition: if the character exists at the end of the string, it is removed.
> a = "abc-"
=> "abc-"
>> a.chop! if a[-1] == 45 # if last character is a minus sign chop it off
=> 45
>> a
=> "abc"
try the following
text.chop! if text[text.length-1,1] == "-"
text.chop! removes the last character and saves it to the same object