Array returning Fixnum instead of String - ruby

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"

Related

Ruby not allowing me to compare values

I made the code below, but when I run it, including if I pick the correct number, the console prints the debug. Why is this? What am I doing wrong?
puts 'Welcome to the number guessing game. I will pick a number between 1-100. It will be your job to guess the number. If you are incorrect, I will tell you if your guess is higher or lower than my number, I will let you know.'
puts "Time to guess!"
mine = (rand(1..100))
puts mine
grabber = gets.chomp!
if mine == grabber
puts 'That\'s it!'
else
print 'debug'
end
You're comparing values of two different types. gets returns a string, rand(1..100) returns an integer. You can't compare them directly. You need to convert them to the same type, either both integer or both string.
Try using to_i on the string to convert it to an integer:
if mine == grabber.to_i
As #meagar said, you are comparing different types (a string from gets and a number from rand) which will always returning false.
That being said, you have a couple of different ways to coerce/convert datatypes in ruby.
The most common one, as #maeger showed, is using to_i, however it can lead to some strange behaviours as any string that isn't easily parsed as an integer will return 0.
2.5.3 :001 > 'potato'.to_i
=> 0
2.5.3 :002 > '0xff'.to_i
=> 0
If you want to avoid this you can use Integer(arg), this is actually a method defined in Kernel that will do its best to verify if the string is actually convertible into an integer and if it fails it will raise an ArgumentError.
2.5.3 :001 > Integer('potato')
=> ArgumentError (invalid value for Integer(): 'potato')
2.5.3 :002 > Integer('2')
=> 2
2.5.3 :003 > Integer('0xff') # Hexadecimal
=> 255
2.5.3 :004 > Integer('0666') # Octal
=> 438
2.5.3 :005 > Integer('0b1110') # Binary
=> 14

Ruby - Converting Strings to CamelCase

I'm working on an exercise from Codewars. The exercise is to convert a string into camel case. For example, if I had
the-stealth-warrior
I need to convert it to
theStealthWarrior
Here is my code
def to_camel_case(str)
words = str.split('-')
a = words.first
b = words[1..words.length - 1].map{|x|x.capitalize}
new_array = []
new_array << a << b
return new_array.flatten.join('')
end
I just tested it out in IRB and it works, but in codewars, it won't let me pass. I get this error message.
NoMethodError: undefined method 'map' for nil:NilClass
I don't understand this, my method was definitely right.
You need to think about edge cases. In particular in this situation if the input was an empty string, then words would be [], and so words[1..words.length - 1] would be nil.
Codewars is probably testing your code with a range of inputs, including the emplty string (and likely other odd cases).
The following works in Ruby 2 for me, even if there's only one word in the input string:
def to_camel_case(str)
str.split('-').map.with_index{|x,i| i > 0 ? x.capitalize : x}.join
end
to_camel_case("the-stealth-warrior") # => "theStealthWarrior"
to_camel_case("warrior") # => "warrior"
I know .with_index exists in 1.9.3, but I can't promise it will work with earlier versions of Ruby.
A simpler way to change the text is :
irb(main):022:0> 'the-stealth-warrior'.gsub('-', '_').camelize
=> "TheStealthWarrior"
This should do the trick:
str.gsub("_","-").split('-').map.with_index{|x,i| i > 0 ? x.capitalize : x}.join
It accounts for words with underscores
Maybe there's a test case with only one word?
In that case, you'd be trying to do a map on words[1..0], which is nil.
Add logic to handle that case and you should be fine.

is there a way to get a random element from an array and also delete it just that single element

I want:
1.9.3p392 :015 > a=["birds","things","people","people"]
=> ["birds", "things", "people","people"]
1.9.3p392 :016 > a.sample
=> "people"
1.9.3p392 :017 > a
=> ["birds", "things","people"]
1.9.3p392 :018 >
but doesn't look like sample supports this. Anything I'm missing in sample's arguments? I'm aware I could I could delete with what is returned but that will delete ALL the members that are that value not just that single instance.
thx
Here is a more traditional version I initially suggested which removes the element by index. This method mutates the original array, but also preserves order.
a = ["birds","things","people","people"]
i = rand(a.size)
# delete_at returns the element removed, or nil
elm = a.delete_at(i)
Here is another solution that doesn't have side-effects (it utilizes a one of the sample-size forms). This approach changes the order of the remaining elements and may be "less efficient" for large arrays.
a = ["birds","things","people","people"]
elm, *rest = a.sample(a.size)
I actually would not use the 2nd solution and would manually duplicate the array first if that is what I wanted - after reviewing it, it seems too "clever" and convoluted.
You could do this:
a = ["birds","things","people","people"]
a.delete_at(a.find_index(a.sample))

Accessing the last key–value pair in a Ruby (1.9) hash

As of Ruby 1.9, hashes retain insertion order which is very cool. I want to know the best way to access the last key–value pair.
I've written some code which does this:
hash.values.last
This works and is very easy to comprehend, but perhaps it's possible to access the last value directly, rather that via an intermediary (the array of values). Is it?
Hash have a "first" method, but that return the first pair in array mode, for last, you can try:
my_hash.to_a.last
this return last pair in array mode like "first method"
One more alternative that I'm using myself:
hash[hash.keys.last]
which works out better when you want to directly assign a value onto the last element of the hash:
2.4.1 :001 > hash = {foo: 'bar'}
=> {:foo=>"bar"}
2.4.1 :002 > hash[hash.keys.last] = 'baz'
=> "baz"
2.4.1 :003 > hash.values.last = 'bar'
NoMethodError: undefined method `last=' for ["baz"]:Array
Did you mean? last
from (irb):3
from /home/schuylr/.rvm/rubies/ruby-2.4.1/bin/irb:11:in `<main>'
Nothing built in, no. But you could monkey-patch one if you were so inclined (not usually recommended, of course):
class Hash
def last_value
values.last
end
end
And then:
hash.last_value
I just did this for a very large hash:
hash.reverse_each.with_index do |(_, value), index|
break value if (index == 0)
end

What's the opposite of chr() in 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

Resources