This question already has answers here:
what is "?" in ruby
(3 answers)
Closed 7 years ago.
I came across this piece of ruby code:
str[-1]==??
What is the double question mark all about? Never seen that before.
Ruby 1.8 has a ?-prefix syntax that turns a character into its ASCII code value. For example, ?a is the ASCII value for the letter a (or 97). The double question mark you see is really just the number 63 (or the ASCII value for ?).
?a # => 97
?b # => 98
?c # => 99
?\n # => 10
?? # => 63
To convert back, you can use the chr method:
97.chr # => "a"
10.chr # => "\n"
63.chr # => "?"
??.chr # => "?"
In Ruby 1.9, the ?a syntax returns the character itself (as does the square bracket syntax on strings):
?? # => "?"
"What?"[-1] # => "?"
As Ryan says, the ? prefix gives you the ASCII value of a character. The reason why this is useful in this context is that when you use the index notation on a string in Ruby 1.8 the ASCII value is returned rather than the character. e.g.
irb(main):009:0> str = 'hello'
=> "hello"
irb(main):010:0> str[-1]
=> 111
so the following wouldn't test if the last character of a string was the letter 'o'
irb(main):011:0> str[-1] == 'o'
=> false
but this would:
irb(main):012:0> str[-1] == ?o
=> true
and (provided you know what the ? does!) this is slightly clearer than
irb(main):013:0> str[-1] == 111
=> true
Related
This question already has answers here:
What does the unary question mark (?) operator do?
(4 answers)
Closed 2 years ago.
Why when I use a question mark at the beginning of a line it makes it into a String?
For example:
?a
# => "a"
?1
# => "1"
?(
# => "("
?a + "b"
# => "ab"
When I use more than 1 character it raises error:
?ab
# SyntaxError (syntax error, unexpected '?')
Why it happens?
I found the answer in docs:
There is also a character literal notation to represent single character strings, which syntax is a question mark (?) followed by a single character or escape sequence that corresponds to a single codepoint in the script encoding
?a #=> "a"
?abc #=> SyntaxError
?\n #=> "\n"
?\s #=> " "
?\\ #=> "\\"
?\u{41} #=> "A"
?\C-a #=> "\x01"
?\M-a #=> "\xE1"
?\M-\C-a #=> "\x81"
?\C-\M-a #=> "\x81", same as above
?あ #=> "あ"
This question already has answers here:
What does the underscore mean in literal numbers?
(4 answers)
Closed 8 years ago.
What is difference and why did someone write number with underscore?
irb(main):001:0> a = 11_223
=> 11223
irb(main):002:0> b = 11223
=> 11223
irb(main):003:0> a == b
=> true
irb(main):004:0> a === b
=> true
irb(main):005:0> 11_223 === 11223
=> true
When you write 1 million in numbers, you would usually do:
1,000,000
and not:
1000000
To make it more readable.
You can do the same thing in Ruby with an underscore:
1_000_000
Ruby can't use the ,, because that's already used in other things (like function arguments), so the "strange" underscore character is used.
I have an Excel column containing part numbers. Here is a sample
As you can see, it can be many different datatypes: Float, Int, and String. I am using roo gem to read the file. The problem is that roo interprets integer cells as Float, adding a trailing zero to them (16431 => 16431.0). I want to trim this trailing zero. I cannot use to_i because it will trim all the trailing numbers of the cells that require a decimal in them (the first row in the above example) and will cut everything after a string char in the String rows (the last row in the above example).
Currently, I have a a method that checks the last two characters of the cell and trims them if they are ".0"
def trim(row)
if row[0].to_s[-2..-1] == ".0"
row[0] = row[0].to_s[0..-3]
end
end
This works, but it feels terrible and hacky. What is the proper way of getting my Excel file contents into a Ruby data structure?
def trim num
i, f = num.to_i, num.to_f
i == f ? i : f
end
trim(2.5) # => 2.5
trim(23) # => 23
or, from string:
def convert x
Float(x)
i, f = x.to_i, x.to_f
i == f ? i : f
rescue ArgumentError
x
end
convert("fjf") # => "fjf"
convert("2.5") # => 2.5
convert("23") # => 23
convert("2.0") # => 2
convert("1.00") # => 1
convert("1.10") # => 1.1
For those using Rails, ActionView has the number_with_precision method that takes a strip_insignificant_zeros: true argument to handle this.
number_with_precision(13.00, precision: 2, strip_insignificant_zeros: true)
# => 13
number_with_precision(13.25, precision: 2, strip_insignificant_zeros: true)
# => 13.25
See the number_with_precision documentation for more information.
This should cover your needs in most cases: some_value.gsub(/(\.)0+$/, '').
It trims all trailing zeroes and a decimal point followed only by zeroes. Otherwise, it leaves the string alone.
It's also very performant, as it is entirely string-based, requiring no floating point or integer conversions, assuming your input value is already a string:
Loading development environment (Rails 3.2.19)
irb(main):001:0> '123.0'.gsub(/(\.)0+$/, '')
=> "123"
irb(main):002:0> '123.000'.gsub(/(\.)0+$/, '')
=> "123"
irb(main):003:0> '123.560'.gsub(/(\.)0+$/, '')
=> "123.560"
irb(main):004:0> '123.'.gsub(/(\.)0+$/, '')
=> "123."
irb(main):005:0> '123'.gsub(/(\.)0+$/, '')
=> "123"
irb(main):006:0> '100'.gsub(/(\.)0+$/, '')
=> "100"
irb(main):007:0> '127.0.0.1'.gsub(/(\.)0+$/, '')
=> "127.0.0.1"
irb(main):008:0> '123xzy45'.gsub(/(\.)0+$/, '')
=> "123xzy45"
irb(main):009:0> '123xzy45.0'.gsub(/(\.)0+$/, '')
=> "123xzy45"
irb(main):010:0> 'Bobby McGee'.gsub(/(\.)0+$/, '')
=> "Bobby McGee"
irb(main):011:0>
Numeric values are returned as type :float
def convert_cell(cell)
if cell.is_a?(Float)
i = cell.to_i
cell == i.to_f ? i : cell
else
cell
end
end
convert_cell("foobar") # => "foobar"
convert_cell(123) # => 123
convert_cell(123.4) # => 123.4
I have the following string:
/Users/patelc75/Documents/code/haloror/dialup/H200000787_1313406125/H200000787_1313389058_1.xml
In Ruby, how do I extract the first 10 character substring that starts with the letter H and contains 9 digits (digits only) after the H. In this above example, the substring would be H200000787
String#[] method is what you need:
str = '/Users/patelc75/Documents/code/haloror/dialup/H200000787_1313406125/H200000787_1313389058_1.xml'
puts str[/H\d{9}/] #=> H200000787
irb(main):001:0> s = "/Users/patelc75/Documents/code/haloror/dialup/H200000787_1313406125/H200000787_1313389058_1.xml"
=> "/Users/patelc75/Documents/code/haloror/dialup/H200000787_1313406125/H200000787_1313389058_1.xml"
irb(main):002:0> s =~ /H\d{9}/
=> 46
irb(main):003:0> $&
=> "H200000787"
In Ruby 1.9.2, I found a way to make two strings that have the same bytes, same encoding, and are equal, but they have a different length and different characters returned by [].
Is this a bug? If it is not a bug, then I'd like to fully understand it. What kind of information is stored inside Ruby 1.9.2 String objects that allows these two strings to behave differently?
Below is the code that reproduces this behavior. The comments that start with #=> show you what output I am getting from this script, and the parenthetical words tell you my judgment of that output.
#!/usr/bin/ruby1.9
# coding: utf-8
string1 = "\xC2\xA2" # A well-behaved string with one character (¢)
string2 = "".concat(0xA2) # A bizarre string very similar to string1.
p string1.bytes.to_a #=> [194, 162] (good)
p string2.bytes.to_a #=> [194, 162] (good)
puts string1.encoding.name #=> UTF-8 (good)
puts string2.encoding.name #=> UTF-8 (good)
puts string1 == string2 #=> true (good)
puts string1.length #=> 1 (good)
puts string2.length #=> 2 (weird!)
p string1[0] #=> "¢" (good)
p string2[0] #=> "\xC2" (weird!)
I am running Ubuntu and compiled Ruby from source. My Ruby version is:
ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-linux]
It is Ruby's bug and fixed r29848.
Matz mentioned this question via Twitter:
http://twitter.com/matz_translator/status/6597021662187520
http://twitter.com/matz_translator/status/6597055132733440
"It's hard to determine as a bug but, it's not acceptable to leave it as is. I'd prefer to fix this issue."
I think the problem is in the string's encoding. Check out James Grey's Shades of Gray: Ruby 1.9's String article on Unicode encoding.
Additional odd behavior:
# coding: utf-8
string1 = "\xC2\xA2"
string2 = "".concat(0xA2)
string3 = 0xC2.chr + 0xA2.chr
string1.bytes.to_a # => [194, 162]
string2.bytes.to_a # => [194, 162]
string3.bytes.to_a # => [194, 162]
string1.encoding.name # => "UTF-8"
string2.encoding.name # => "UTF-8"
string3.encoding.name # => "ASCII-8BIT"
string1 == string2 # => true
string1 == string3 # => false
string2 == string3 # => true
string1.length # => 1
string2.length # => 2
string3.length # => 2
string1[0] # => "¢"
string2[0] # => "\xC2"
string3[0] # => "\xC2"
string3.unpack('C*') # => [194, 162]
string4 = string3.unpack('C*').pack('C*') # => "\xC2\xA2"
string4.encoding.name # => "ASCII-8BIT"
string4.force_encoding('UTF-8') # => "¢"
string3.force_encoding('UTF-8') # => "¢"
string3.encoding.name # => "UTF-8"