what is [-1, 1] in this ruby code? - ruby

I am looking at an example of code and confused.
def self.type(input)
input.strip!
return 'question' if input[-1,1] == '?'
end
So, input[-1] makes sense, it is checking if the last character is a question mark. What does the 1 do? Also, all the example tests pass without the 1.

input[-1,1] means reading 1 character from the last character. It gives the same result as input[-1] because you are reading just 1 character from the last character.
Look at some examples to understand more:
❯ irb
2.3.0 :001 > input = 'lenin'
=> "lenin"
2.3.0 :002 > input[-1]
=> "n"
2.3.0 :003 > input[-1,1]
=> "n"
2.3.0 :004 > input[-2]
=> "i"
2.3.0 :005 > input[-2, 1]
=> "i"
2.3.0 :006 > input[-2, 2]
=> "in"
2.3.0 :007 > input[-2, 3]
=> "in"

Related

How do I do a reverse to_i?

I'm using Ruby 2.4. If there are numbers at the beginning of my string, I can get the value as an integer by doing
2.4.0 :003 > s = "13s"
=> "13s"
2.4.0 :004 > s.to_i
=> 13
However, how do I get the numbers as an integer if they are at the end of my string? For instance, in
s13
I have "13" at the end of the string, but obviously, .to_i won't extract that ...
2.4.0 :005 > s = "s13"
=> "s13"
2.4.0 :006 > s.to_i
=> 0
What's a generic way of extracting the numerical portion of the end of a string? IF the string is
abcd
I'd expect the numerical portion to just be zero.
One solution would be this one
"s13".reverse.to_i.to_s.reverse
Or extract the digits from the end of the string
"s13"[/\d+\z/]

Ruby - Array.length returning character count instead of element count

I'm using Ruby 2.0 for a Rails project and am having some issues obtaining the element length of an array in the console.
First example
2.0.0-p353 :001 > search = "test"
=> "test"
2.0.0-p353 :002 > search.split
=> ["test"]
2.0.0-p353 :003 > search.length
=> 4
Second example
2.0.0-p353 :001 > search = "testOne, TestTwo"
=> "testOne, TestTwo"
2.0.0-p353 :002 > search.split(/[\s,]+/)
=> ["testOne", "TestTwo"]
2.0.0-p353 :003 > search.length
=> 16
How do I return the element count instead of the character count?
Well, you're not assigning your split array that's why you're seeing the discrepancy.
What you're actually doing is defining a string search and then trying to manipulate that same string.
Try this
testArray = search.split
testArray.size
>> 1
In the first example you are getting the length of the "test" string, not of the ["test"] array. You should assign it to a variable first.
i.e.:
search = "test" # => "test"
array = search.split # => ["test"]
array.length # => 1

How do I convert array of numerics to an integer?

I am trying to convert the following array:
2.0.0-p0 :021 > test = 1, 440, 840
=> [1, 440, 840]
to the following integer:
1440840
If I do a split(',') and then join them, it works, but I'm sure there is a better way.
No need to use split if it's an Array. Just do:
test.join.to_i
Sample run with join:
2.0.0-p195 :007 > t.is_a? Array
=> true
2.0.0-p195 :008 > t.join.to_i
=> 1440840
2.0.0-p195 :009 >
How about
test.inject { |ttl, n| ttl * 1000 + n }
Here are some things to meditate on:
STRING = '1,440,840'
STRING.gsub(',', '').to_i # => 1440840
STRING.tr(',', '').to_i # => 1440840
STRING.delete(',').to_i # => 1440840
STRING.scan(/\d+/).join.to_i # => 1440840
require 'scanf'
STRING.scanf('%d,%d,%d').join.to_i # => 1440840
We don't see scanf used much in Ruby, but it's a mainstay in C, and used often in Perl. It's the opposite side of Kernels's printf, sprintf, format and String's %.

How can I escape a Ruby symbol with quotes only if needed?

IRB and Rails console both have a nice way of outputting symbols that only quote-escapes them when necessary. Some examples:
1.9.3p194 :001 > "#test".to_sym
=> :#test
1.9.3p194 :002 > "#Test".to_sym
=> :#Test
1.9.3p194 :003 > "#123".to_sym
=> :"#123"
1.9.3p194 :004 > "##_test".to_sym
=> :##_test
1.9.3p194 :005 > "test?".to_sym
=> :test?
1.9.3p194 :006 > "test!".to_sym
=> :test!
1.9.3p194 :007 > "_test!".to_sym
=> :_test!
1.9.3p194 :008 > "_test?".to_sym
=> :_test?
1.9.3p194 :009 > "A!".to_sym
=> :"A!"
1.9.3p194 :010 > "#a!".to_sym
=> :"#a!"
How would you do this yourself, so that you could do:
puts "This is valid code: #{escape_symbol(some_symbol)}"
The easiest and best way to do this is via Symbol's inspect method:
1.9.3p194 :013 > puts "This is valid code: #{"#a!".to_sym.inspect}"
This is valid code: :"#a!"
=> nil
1.9.3p194 :014 > puts "This is valid code: #{"a!".to_sym.inspect}"
This is valid code: :a!
You could look at the sym_inspect(VALUE sym) method in string.c in Ruby 1.9.3 that does that, if you're curious.
So, even though you don't need another method to call inspect, this would be the simplest implementation:
def escape_symbol(sym)
sym.inspect
end
Here's my attempt at implementing with a few regexs, although I'd suggest using inspect instead if you can:
def escape_symbol(sym)
sym =~ /^[#a-zA-Z_]#?[a-zA-Z_0-9]*$/ || sym =~ /^[a-z_][a-zA-Z_0-9]*[?!]?$/ ? ":#{sym}" : ":\"#{sym.gsub(/"/, '\\"')}\""
end

What are values mapped to?

I don't understand how Ruby hashes work.
I expect these:
a = 'a'
{a => 1}[a] # => 1
{a: 1}[:a] # => 1
{2 => 1}[2] # => 1
How does this work?
{'a' => 1}['a'] # => 1
The first string 'a' is not the same object as the second string 'a'.
Ruby doesn't use object equality (equal?) for comparing hash keys. It wouldn't be very useful if it did after all.
Instead it uses eql?, which for strings is the same as ==
As a footnote to other answers, you can let a hash behave like you expected:
h = {'a'=> 1}
p h['a'] #=> 1
h.compare_by_identity
p h['a'] #=> nil ; not the same object
some_hash[k] = v
Basically, when you do this, what is stored is not a direct association k => v. Instead of that, k is asked for a hash code, which is then used to map to v.
Equal values yield equal hash codes. That's why your last example works the way it does.
A couple of examples:
1.9.3p0 :001 > s = 'string'
=> "string"
1.9.3p0 :002 > 'string'.hash
=> -895223107629439507
1.9.3p0 :003 > 'string'.hash == s.hash
=> true
1.9.3p0 :004 > 2.hash
=> 2271355725836199018
1.9.3p0 :005 > nil.hash
=> 2199521878082658865

Resources