Ruby: Rubeque: Variable in regexp? - ruby

I'm solving http://www.rubeque.com/problems/a-man-comma--a-plan-comma--a-canal--panama-excl-/solutions but I'm a bit confused about treating #{} as comment in regexp.
My code look like this now
def longest_palindrome(txt)
txt[/#{txt.reverse}/]
end
I tried txt[/"#{txt.reverse}"/] or txt[#{txt.reverse}] but nothing works as I wish. How should I implicate variable into regexp?

This is not something you can do with a regex.
While you could use variable interpolation in the construction of a regex (see the other answers/comments), that wouldn't help you here. You could only use that to reverse a literal string, not a regex match result. Even if you could, you still wouldn't have solved the "find the longest palindrome" part, at least not with acceptable runtime performance.
Use a different approach to the problem.

It is hard to tell how do you wish that happens without examples, but I suppose you are after
txt[/#{Regexp.escape(txt.reverse)}/]
See the Regexp#escape method

Related

syntax for rejecting items in array with regex

I have this working for my array:
my_arr.delete_if{|x| x=~/achievement\..*?/}
it deletes all strings in the array that match the pattern achievement.. Is there a similar one-liner to do the reverse (only accept strings that contain achievement.?
use Array#keep_if instead of #delete_if
my_arr.keep_if{|x| x=~/achievement\..*?/}
No need to modify the regex, you can use Array#keep_if.
my_arr.keep_if{|x| x=~/achievement\..*?/}
Okay, the better solution is definitely to use keep_if.
The OP asks whether there is a way to
only accept strings that contain "achievement."
So yes, again not the best way but you could use negative lookahead: (?!exp):
my_arr.delete_if{|x| x=~/(?!achievement\..*?)/}
A further alternative, still using delete_if is to use the "not equals matching" operator (thanks #Cary):
my_arr.delete_if{|x| x!~/achievement\..*?/}
Again, thanks #Cary, for pointing out that this is not pleasant logic to find in anyone's code so use keep_if

Ruby regex return match based on negation

I just want to capture the part of the string in nbnbaasd<sd which appears before any a.
I want it to return nbnb as the match.
/.+(?!a)/.match("nbnbaasd<sd") # returns the whole string
Just use a negated character set:
/[^a]+/.match("nbnbaasd<sd")
It's far more efficient than the look-ahead method.
See it here in action: http://regexr.com?32288
It returns the whole string because indeed, "nbnbaasd<sd" is not followed by an "a".
Try this.
/.+?(?=a)/.match("nbnbaasd<sd")
(You do not actually need to use a lookahead to achieve this, but perhaps you've simplified your problem and in your real problem you do need a zero-width assertion for some reason. So this is a solution as close as possible to the one you've attempted.)

Ruby regex: extract a list of urls from a string

I have a string of images' URLs and I need to convert it into an array.
http://rubular.com/r/E2a5v2hYnJ
How do I do this?
URI.extract(your_string)
That's all you need if you already have it in a string. I can't remember, but you may have to put require 'uri' in there first. Gotta love that standard library!
Here's the link to the docs URI#extract
Scan returns an array
myarray = mystring.scan(/regex/)
See here on regular-expressions.info
The best answer will depend very much on exactly what input string you expect.
If your test string is accurate then I would not use a regex, do this instead (as suggested by Marnen Laibow-Koser):
mystring.split('?v=3')
If you really don't have constant fluff between your useful strings then regex might be better. Your regex is greedy. This will get you part way:
mystring.scan(/https?:\/\/[\w.-\/]*?\.(jpe?g|gif|png)/)
Note the '?' after the '*' in the part capturing the server and path pieces of the URL, this makes the regex non-greedy.
The problem with this is that if your server name or path contains any of .jpg, .jpeg, .gif or .png then the result will be wrong in that instance.
Figuring out what is best needs more information about your input string. You might for example find it better to pattern match the fluff between your desired URLs.
Use String#split (see the docs for details).
Part of the problem is in rubular you are using https instead of http.. this gets you closer to what you want if the other answers don't work for you:
http://rubular.com/r/cIjmjxIfz5

ALL CAPS to Normal case

I'm trying to find an elegant solution on how to convert something like this
ALL CAPS TEXT. "WHY ANYONE WOULD USE IT?" THIS IS RIDICULOUS! HELP.
...to regular-case. I could more or less find all sentence-starting characters with:
(?<=^|(\. \"?)|(! ))[A-Z] #this regex sure should be more complex
but (standard) Ruby neither allows lookbehinds, nor it is possible to apply .capitalize to, say, gsub replacements. I wish I could do this:
"mytext".gsub(/my(regex)/, '\1'.capitalize)
but the current working solution would be to
"mytext".split(/\. /).each {|x| p x.capitalize } #but this solution sucks
First of all, notice that what you are trying to do will only be an approximation.
You cannot correctly tell where the sentence boundaries are. You can approximate it as The beginning of the entire string or right after a period, question mark, or exclamation mark followed by spaces. But then, you will incorrectly capitalize "economy" in "U.S. economy".
You cannot correctly tell which words should be capitalized. For example, "John" will be "john".
You may want to do some natural language processing to give you a close-to-correct result in many cases, but these methods are only probablistically correct. You will never get a perfect result.
Understanding these limitations, you might want to do:
mytext.gsub(/.*?(?:[.?!]\s+|\z)/, &:capitalize)

Ruby gsub : is there a better way

I need to remove all leading and trailing non-numeric characters. This is what I came up with. Is there a better implementation.
puts s.gsub(/^\D+/,'').gsub(/\D+$/,'')
Instead of eliminating what you don't want, it's often clearer to select what you do want (using parentheses). Also, this only requires one regex evaluation:
s.match(/^\D*(.*?)\D*$/)[1]
Or, this convenient shorthand:
s[/^\D*(.*?)\D*$/, 1]
Perhaps a single #gsub(/(^\D+)|(\D+$)/, '')
Also, when in doubt Rubular it.

Resources