tags:

views:

775

answers:

3

Hi everyone,

I have a problem I can't for the life of me solve. I'm writing a Ruby app (I've been a PHP developer for 8 years, just starting with Ruby) that sells tickets for a concert hall. Each seat has a row (a...z) and a number (1...x). The database model has row (string) and num (int) for each seat.

How can I convert my array of seats from the database into a 2d array? For example, seat A1 would go into seat[1][1] = "value"; seat C4 would map to seat[3][4] = value. The issue is converting the row string to Ascii and subtracting the offset? Or is there an easier way?

Many thanks

+3  A: 

The simplest way is probably to use a hash instead. For example: seat['A'][1] = value

But if you really need an array for some reason, then the method you describe is the simplest. Assuming the row string is a single character 'A' through 'Z', you can do it using row_string[0] - ?A (or row_string[0] - ?A + 1 if you want the index starting at 1 as in your example). For a multi-character version where row AA is after row Z, you can do this in 1.8.7 and newer:

row_num = row_string.bytes.inject(0) {|total, x| total = total * 26 + x - ?A + 1}

You may want to upcase your row string beforehand, just to be on the safe side.

In 1.8.6 and below, String does not have a bytes method. You can accomplish the same thing by doing:

row_num = 0
row_string.each_byte {|x| row_num = row_num * 26 + x - ?A + 1}
Pesto
I agree, a hash is the best way of dealing with this.
Corban Brook
Many thanks indeed. Hashes are certainly the easiest way forward. However:outs = {}for seat in self.seats outs[seat.num][seat.row] = "yes"end return outsProduces The error occurred while evaluating nil.[]=. Both seat.row and seat.num have asserted values, so I'm guessing it must be a syntax error.Thanks for all your help.
Dan Hill
It's not a syntax error, you just need to create the array for each row before trying to assign elements to it. Try this: outs = {}; for seat in self.seats; outs[seat.num] ||= []; outs[seat.num][seat.row] = "yes"; end The "outs[seat.num] ||= []" line will set outs[seat.num] to be an empty array if it doesn't have a value yet.Also, you might be better off using true instead of "yes".
Pesto
A: 

Well to get the index of a letter you could do something like this

('A'..'Z').to_a.index('C')

which would return 2

I notice in the array examples you gave you started A = 1 instead of 0.

Corban Brook
+2  A: 

Ok, the solution I've come up with that seems to do the trick:

seat_array = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc) }
for seat in self.seats
seat_array[seat.row.downcase][seat.num] = seat
end 
return seat_array

Many thanks to everyone for such quick and useful responses. I'll certainly be helping others with PHP!

Dan Hill