What's the opposite of chr() in Ruby? - ruby

In many languages there's a pair of functions, chr() and ord(), which convert between numbers and character values. In some languages, ord() is called asc().
Ruby has Integer#chr, which works great:
>> 65.chr
A
Fair enough. But how do you go the other way?
"A".each_byte do |byte|
puts byte
end
prints:
65
and that's pretty close to what I want. But I'd really rather avoid a loop -- I'm looking for something short enough to be readable when declaring a const.

If String#ord didn't exist in 1.9, it does in 2.0:
"A".ord #=> 65

In Ruby up to and including the 1.8 series, the following will both produce 65 (for ASCII):
puts ?A
'A'[0]
The behavior has changed in Ruby 1.9, both of the above will produce "A" instead. The correct way to do this in Ruby 1.9 is:
'A'[0].ord
Unfortunately, the ord method doesn't exist in Ruby 1.8.

Try:
'A'.unpack('c')

I'd like to +1 dylanfm and AShelly's comment but add the [0]:
'A'.unpack('C')[0]
The unpack call returns an Array containing a single integer, which is not always accepted where an integer is wanted:
$ ruby -e 'printf("0x%02X\n", "A".unpack("C"))'
-e:1:in `printf': can't convert Array into Integer (TypeError)
from -e:1
$ ruby -e 'printf("0x%02X\n", "A".unpack("C")[0])'
0x41
$
I'm trying to write code that works on Ruby 1.8.1, 1.8.7 and 1.9.2.
Edited to pass C to unpack in uppercase, because unpack("c") gives me -1 where ord() gives me 255 (despite running on a platform where C's char is signed).

Just came across this while putting together a pure Ruby version of Stringprep via RFCs.
Beware that chr fails outside [0,255], instead use 1.9.x - 2.1.x portable replacements:
[22] pry(main)> "\u0221".ord.chr
RangeError: 545 out of char range
from (pry):2:in 'chr'
[23] pry(main)> x = "\u0221".unpack('U')[0]
=> 545
[24] pry(main)> [x].pack('U')
=> "ȡ"
[25] pry(main)>

Additionally, if you have the char in a string and you want to decode it without a loop:
puts 'Az'[0]
=> 65
puts 'Az'[1]
=> 122

How about
puts ?A

You can have these:
65.chr.ord
'a'.ord.chr

If you don't mind pulling the values out of an array, you can use "A".bytes

I'm writing code for 1.8.6 and 1.9.3 and I couldn't get any of these solutions to work in both environments :(
However, I came across another solution:
http://smajnr.net/2009/12/ruby-1-8-nomethoderror-undefined-method-ord-for-string.html
That didn't work for me either but I adapted it for my use:
unless "".respond_to?(:ord)
class Fixnum
def ord
return self
end
end
end
Having done that, then the following will work in both environments
'A'[0].ord

Related

Why does Ruby string formatting with hashes behave inconsistently across versions?

I wrote some code that used a "dynamic hash" to return values for keys, where the values were calculated. I tested it under irb (RUBY_VERSION 2.3.3) and everything seemed good. Below is a trivial example demonstrating the idea.
PROPS = Hash.new { |hash,key| key.to_s + "!" }
"Foo: %{foo} Bar: %{bar}" % PROPS # => "Foo: foo! Bar: bar!"
PROPS[:xyzzy] # => "xyzzy!"
But then deploying my code into the environment where it used (a plugin for the modeling tool Sketchup) which apparently has Ruby 2.2.4 the string formatting example above yields a KeyError: key{foo} not found.
PROPS = Hash.new { |hash,key| key.to_s + "!" }
"Foo: %{foo} Bar: %{bar}" % PROPS # KeyError: key{foo} not found
PROPS[:xyzzy] # => "xyzzy!"
But accessing the hash with any key works fine... Reading at http://ruby-doc.org/core-2.2.4/Kernel.html#method-i-sprintf doesn't provided much in the way of specifying why hash defaults would not behave as expected.
Obviously I can do different things, like invent my own replacement functions and variable syntax. As an aside, apparently the "hashes" passed to "%" or sprintf must actually BE Hash objects, violating Ruby's supposed duck-typing flexibility.
I can confirm that it does not work in Ruby 2.1.5 .
I will give some hints on how you could find out which ruby code to define to get the stuff going without reading C or Ruby code from MRI.
I know, this is not a full answer, but the text is too long to give in a comment.
Following is an irb session
>> detector = Object.new
=> #<Object:0x00000002257900>
>> def detector.method_missing m
>> puts m.to_s
>> end
=> :method_missing
>> "Foo: %{fnoo} Bar: %{bar}" % detector
to_ary
to_hash
ArgumentError: one hash required
from (irb):37:in `%'
from (irb):37
from /home/felix/.rvm/rubies/ruby-2.1.5/bin/irb:11:in `<main>'
This tells us that during interpolation methods were called that are not implemented by our dummy "detector" Object (to_hash to be precisely; through other tests I know that to_ary is also called if given object is a Hash, so we can ignore that one).
It does however not tell us whether already something like detector.class or detector is_a Hash? etcpp. were called.
Now I await the downvotes ;)
Btw, if you want to dive in via C - and I came to believe that this is probably needed in this case - you can start digging here: https://github.com/ruby/ruby/blob/6d728bdae9de565ad9d0b2fee2d4c2a33c6f4eac/sprintf.c#L579 (more or less "sprintf" on ruby 2.1).

Ruby - cannot convert individual chars in string to ASCII

I am trying to run the following code on http://repl.it/languages/Ruby/, but I am encountering a NoMethodError:
a = "string"
a.each_char do |c|
puts c.ord
end
The error details are as follows:
(eval):1: undefined method `ord' for "s":String (NoMethodError)
from (eval):0:in `each_char'
from (eval):0
Please could somebody explain to me why my code does not work?
The each_char method of String yields each character as a separate String.
The Ruby version running on repl.it is quite old (1.8.7). The String class in that version of Ruby doesn't define an ord method, so your code fails to run with a NoMethodError.
ord was added to String in Ruby 1.9, so your code will run on newer versions of Ruby.
On Ruby 1.8.7 (and repl.it), you could use one of the following alternatives instead:
a = "string"
a.each_char do |c|
puts c[0]
end
a = "string"
a.each_byte do |c|
puts c
end
However, please note that these examples won't behave identically to your original code if your string uses a multi-byte encoding. The ord method returns a Unicode code point. The Ruby 1.8.7 examples will give you individual bytes.
The code as is will print the ascii code of each letter. Perhaps you're looking at the return value which would be the original string "string"?

Array returning Fixnum instead of String

I have an array of arrays similar to:
[["Rosalind_0498", "AAATAAA"], ["Rosalind_2391", "AAATTTT"]]
I I want to get the letter of the first array's second element I would expect to use array[0][1][-1]
This instead of returning 'A' returns 65, it's probably something simple to do with ruby arrays but I'm not sure why it is happening, can someone point me in the right direction?
UPDATE:
Is there a better way to do it then array[0][1][-1..-1]?
Prior to Ruby 1.9, accessing a string char with [] would get you the ascii value of this char.
Just use this in ruby 1.8:
array[0][1][-1].chr
what version of ruby are you using?
2.0.0p0 :001 > a = [["Rosalind_0498", "AAATAAA"], ["Rosalind_2391", "AAATTTT"]]
=> [["Rosalind_0498", "AAATAAA"], ["Rosalind_2391", "AAATTTT"]]
2.0.0p0 :002 > a[0][1][0]
=> "A"
You can try the below:
p [["Rosalind_0498", "AAATAAA"], ["Rosalind_2391", "AAATTTT"]].flatten[1].chr #=> "A"

How does this ruby injection magic work?

I saw a ruby code snippet today.
[1,2,3,4,5,6,7].inject(:+)
=> 28
[1,2,3,4,5,6,7].inject(:*)
=> 5040
The injection here is quite different from those I've seen before, like
[1,2,3,4,5,6,7].inject {|sum, x| sum + x}
Please explain how does it work?
There's no magic, symbol (method) is just one of the possible parameters. This is from the docs:
# enum.inject(initial, sym) => obj
# enum.inject(sym) => obj
# enum.inject(initial) {| memo, obj | block } => obj
# enum.inject {| memo, obj | block } => obj
Ours case is the second one.
You can also rewrite it with traditional block:
op = :+ # parameter of inject call
[1,2,3,4,5,6,7].inject {|sum, x| sum.send(op, x)} # also returns 28
(to answer "how does it work" part)
The :+ is a symbol representing the addition message. Remember that Ruby has a Smalltalk style where just about every operation is performed by sending a message to an object.
As discussed in great detail here, (1..100).inject(&:+) is valid syntax in earlier versions where Rails has added the to_proc extension to Symbol.
The ability to pass just a symbol into inject was new in 1.9 and backported into 1.8.7.
As you can see in the docs, inject can take a block (like you're familiar with) or a symbol that represents the name of a binary operator. It's a useful shorthand for already-defined ops.

Good Ruby shell?

For Python I use PyCrust, which is a nice graphical shell that feels like a good Java IDE (has autocompletion, inline documentation and can save history).
Is there anything similar for Ruby?
If you don't need it to be graphical, you can use irb, wich I think is a part of the ruby package.
It has autocompletion. To enable it say:
require 'irb/completion'
It can also save your history between sessions.
You should write your own .irbrc file to configure it.
I don't know all the features it has, but I guess there are more than the ones I have mentioned here.
Some up and coming ruby shells:
ir - a slim ruby shell
irb2 - rewrite of irb
Thorough documentation of irb:
irb commands
configuring irb
Some gems I've written that'll enhance your ruby shell experience:
hirb - console view framework
bond - enhanced autocompletion i.e. completing method arguments
boson - console command manager and more
The gem "looksee" is helpful for method lookup.
Watch a video at RubyPulse.
You can see all the methods available at the given variable as below.
>> s = "Hello World"
=> "Hello World"
>> lp s
=> String
% casecmp downcase! include? next size sum tr_s
* center dump index next! slice swapcase tr_s!
+ chars each insert oct slice! swapcase! unpack
<< chomp each_byte inspect partition split taguri upcase
<=> chomp! each_char intern replace squeeze taguri= upcase!
== chop each_line is_binary_data? reverse squeeze! to_f upto
=~ chop! empty? is_complex_yaml? reverse! start_with? to_i
[] concat end_with? length rindex strip to_s
[]= count eql? lines rjust strip! to_str
bytes crypt gsub ljust rpartition sub to_sym
bytesize delete gsub! lstrip rstrip sub! to_yaml
capitalize delete! hash lstrip! rstrip! succ tr
capitalize! downcase hex match scan succ! tr!
Enumerable
all? drop enum_cons first max minmax_by reverse_each to_a
any? drop_while enum_slice grep max_by none? select zip
collect each_cons enum_with_index group_by member? one? sort
count each_slice find include? min partition sort_by
cycle each_with_index find_all inject min_by reduce take
detect entries find_index map minmax reject take_while
Comparable
< <= == > >= between?
Object
dump_lookup_path lookup_path taguri to_yaml to_yaml_style
local_methods recent_hisotry taguri= to_yaml_properties
PP::ObjectMixin
pretty_print pretty_print_cycle pretty_print_inspect pretty_print_instance_variables
Kernel
== dup id instance_variables private_methods tap
=== enum_for inspect is_a? protected_methods to_a
=~ eql? instance_eval kind_of? public_methods to_enum
__id__ equal? instance_exec method respond_to? to_s
__send__ extend instance_of? methods send type
class freeze instance_variable_defined? nil? singleton_methods untaint
clone frozen? instance_variable_get object_id taint
display hash instance_variable_set pretty_inspect tainted?

Resources