How do you get the first two characters of a string? - ruby

I have a string "990822". I want to know if the string starts with "99".
I could achieve this by getting the first two characters of the string, then check if this is equal to "99". How do I get the first two characters from a string?

You can use String#start_with?:
"990822".start_with?("99") #=> true

Consider using the method start_with?.
s = "990822"
=> "990822"
s.start_with? "99"
=> true

You can use a range to access string:
"990822"[0...2]
# => "99"
See the String docs

To get the first two characters, the most straightforward way is:
"990822"[0, 2] # => "99"
Using a range inside the method [] is both not straightforward and also creates a range object that is immediately thrown out, which is a waste.
However, the whole question is actually an XY-question.

Related

How to use gsubstitution with more letters

I've printed the code, wit ruby
string = "hahahah"
pring string.gsub("a","b")
How do I add more letter replacements into gsub?
string.gsub("a","b")("h","l") and string.gsub("a","b";"h","l")
didnt work...
*update I have tried this too but without any success .
letters = {
"a" => "l"
"b" => "n"
...
"z" => "f"
}
string = "hahahah"
print string.gsub(\/w\,letters)
You're overcomplicating. As with most method calls in Ruby, you can simply chain #gsub calls together, one after the other:
str = 'adfh'
print str.gsub("a","b").gsub("h","l") #=> 'bdfl'
What you're doing here is applying the second #gsub to the result of the first one.
Of course, that gets a bit long-winded if you do too many of them. So, when you find yourself stringing too many together, you'll want to look for a regex solution. Rubular is a great place to tinker with them.
The way to use your hash trick with #gsub and a regex expression is to provide a hash for all possible matches. This has the same result as the two #gsub calls:
print str.gsub(/[ah]/, {'a'=>'b', 'h'=>'l'}) #=> 'bdfl'
The regex matches either a or h (/[ah]/), and the hash is saying what to substitute for each of them.
All that said, str.tr('ah', 'bl') is the simplest way to solve your problem as specified, as some commenters have mentioned, so long as you are working with single letters. If you need to work with two or more characters per substitution, you'll need to use #gsub.

Regex to get two values in string

I have the following string:
<http://test.host/users?param1=1&param=1>; rel=\"rel_value\"
And I would like to get the URL and the rel value. That is:
http://test.host/users?param1=1&param=1
and
rel_value
I know how to get the URL:
string[/<.*?>/]
But failing to see how to get the rel. Any ideas on a regex that I could get both?
If the string is guaranteed to have that format:
/<(.+)>; rel=\\\"(.+)\\\"/
To be used like so:
m = s.match(/<(.+)>; rel=\\\"(.+)\\\"/)
m[0] #=> http://test.host/users?param1=1&param=1
m[1] #=> rel_value
Additionally, you could just use two regexes to search for each thing in the string:
s[/(?<=<).+(?=>)/] #=> http://test.host/users?param1=1&param=1
s[/(?<=rel=\\\").+(?=\\\")/] #=> rel_value
(These use lookahead and lookbehind to not capture anything besides the values).
As you asked for a regex that does both:
<(.*)>.*rel=\\"(.*)\\"
The first capturing group contains the URL, and the second one the rel value. But you could just do one regex for each.
For the URL:
<(.*)>
And for the rel value:
rel=\\"(.*)\\"
There should be at least one non-regex solution:
str.tr('<>\\\"','').split(';\s+rel=')
#=> ["http://test.host/users?param1=1&param=1; rel=rel_value"]

Using regex to find an exact pattern match in Ruby

How would I go about testing for an exact match using regex.
"car".match(/[ca]+/) returns true.
How would I get the above statement to return false since the regex pattern doesn't contain an "r"? Any string that contains any characters other than "c" and "a" should return false.
"acacaccc" should return true
"acacacxcc" should return false
Add some anchors to it:
/^[ca]+$/
You just need anchors.
"car".match(/^[ca]+$/)
This'll force the entire string to be composed of "c" or "a", since the "^" and "$" mean "start" and "end" of the string. Without them, the regex will succeed as long as it matches any portion of the string.
Turn your logic around and look for bad things:
string.match(/[^ca]/)
string.index(/[^ca]/)
If either of the above are non-nil, then you have a bad string. If you just want to test and don't care about where it matches then:
if string.index(/[^ca]/).nil?
# You have a good string
else
# You have a bad string
For example:
>> "car".index(/[^ca]/).nil?
=> false
>> "caaaacaac".index(/[^ca]/).nil?
=> true
try this
"car".match /^(a|c)+$/
Try this:
"car".match(/^(?:c|a)$/)

Regex to leave desired string remaining and others removed

In Ruby, what regex will strip out all but a desired string if present in the containing string? I know about /[^abc]/ for characters, but what about strings?
Say I have the string "group=4&type_ids[]=2&type_ids[]=7&saved=1" and want to retain the pattern group=\d, if it is present in the string using only a regex?
Currently, I am splitting on & and then doing a select with matching condition =~ /group=\d/ on the resulting enumerable collection. It works fine, but I'd like to know the regex to do this more directly.
Simply:
part = str[/group=\d+/]
If you want only the numbers, then:
group_str = str[/group=(\d+)/,1]
If you want only the numbers as an integer, then:
group_num = str[/group=(\d+)/,1].to_i
Warning: String#[] will return nil if no match occurs, and blindly calling nil.to_i always returns 0.
You can try:
$str =~ s/.*(group=\d+).*/\1/;
Typically I wouldn't really worry too much about a complex regex. Simply break the string down into smaller parts and it becomes easier:
asdf = "group=4&type_ids[]=2&type_ids[]=7&saved=1"
asdf.split('&').select{ |q| q['group'] } # => ["group=4"]
Otherwise, you can use regex a bunch of different ways. Here's two ways I tend to use:
asdf.scan(/group=\d+/) # => ["group=4"]
asdf[/(group=\d+)/, 1] # => "group=4"
Try:
str.match(/group=\d+/)[0]

How do I convert a Ruby string with brackets to an array?

I would like to convert the following string into an array/nested array:
str = "[[this, is],[a, nested],[array]]"
newarray = # this is what I need help with!
newarray.inspect # => [['this','is'],['a','nested'],['array']]
You'll get what you want with YAML.
But there is a little problem with your string. YAML expects that there's a space behind the comma. So we need this
str = "[[this, is], [a, nested], [array]]"
Code:
require 'yaml'
str = "[[this, is],[a, nested],[array]]"
### transform your string in a valid YAML-String
str.gsub!(/(\,)(\S)/, "\\1 \\2")
YAML::load(str)
# => [["this", "is"], ["a", "nested"], ["array"]]
You could also treat it as almost-JSON. If the strings really are only letters, like in your example, then this will work:
JSON.parse(yourarray.gsub(/([a-z]+)/,'"\1"'))
If they could have arbitrary characters (other than [ ] , ), you'd need a little more:
JSON.parse("[[this, is],[a, nested],[array]]".gsub(/, /,",").gsub(/([^\[\]\,]+)/,'"\1"'))
For a laugh:
ary = eval("[[this, is],[a, nested],[array]]".gsub(/(\w+?)/, "'\\1'") )
=> [["this", "is"], ["a", "nested"], ["array"]]
Disclaimer: You definitely shouldn't do this as eval is a terrible idea, but it is fast and has the useful side effect of throwing an exception if your nested arrays aren't valid
Looks like a basic parsing task. Generally the approach you are going to want to take is to create a recursive function with the following general algorithm
base case (input doesn't begin with '[') return the input
recursive case:
split the input on ',' (you will need to find commas only at this level)
for each sub string call this method again with the sub string
return array containing the results from this recursive method
The only slighlty tricky part here is splitting the input on a single ','. You could write a separate function for this that would scan through the string and keep a count of the openbrackets - closedbrakets seen so far. Then only split on commas when the count is equal to zero.
Make a recursive function that takes the string and an integer offset, and "reads" out an array. That is, have it return an array or string (that it has read) and an integer offset pointing after the array. For example:
s = "[[this, is],[a, nested],[array]]"
yourFunc(s, 1) # returns ['this', 'is'] and 11.
yourFunc(s, 2) # returns 'this' and 6.
Then you can call it with another function that provides an offset of 0, and makes sure that the finishing offset is the length of the string.

Resources