views:

211

answers:

3

(can you tell I'm learning Ruby today? :))

I want to determine if the multidimensional array I'm working with is a 'rectangle'--i.e., the rows are the same size. Here's what I'm doing, which works but feels clunky.

if @myArray[0].size != @myArray[[email protected]].size
  raise "This array is not a rectangle."
end

Basically, I'm checking if the first array's size if equal to all the other array's size. Somehow, it seems this isn't "ruby" enough, you know? Anyone have any more elegant solutions?

+3  A: 

Try:

raise 'This array is not a rectangle' \
  if myArray[1..-1].any? { |row| row.size != myArray[0].size }

See http://www.ruby-doc.org/core/classes/Array.html (the [] operator) and http://www.ruby-doc.org/core/classes/Enumerable.html (the any? method)

Cheers, V.

vladr
OOh. nice one. :)
miketaylr
+1  A: 

This will not raise an error:

@my_array = [[1,2,3,4],[1,2,3,4]]
for row in @my_array
  if row.size != @my_array.first.size
    raise "This array is not a rectangle"
  end
end

This will raise an error:

@my_array = [[1,2,3,4],[1,2,3]]
for row in @my_array
  if row.size != @my_array.first.size
    raise "This array is not a rectangle"
  end
end

This code iterates through all the sub-arrays inside the array and checks if their row size is not the same as the first's size and then raises an error if that is the case.

Ryan Bigg
+1  A: 

I might do something like the others have posted, or

if 1 == @myArray.map { |row| row.size }.uniq.size
     # ...
end

You should note that your example code doesn't do what you think it does

# this creates an array that holds a slice
# of elements from @myArray ( a to b inclusive )
@myArray[ a .. b ]
# this just gets the size of the slice
# (equal to b-a+1)
@myArray[a .. b].size

So your if statement actually compared the rowsize with the columnsize (plus 1, since it was 0 to @myArray.size inclusive). It didn't compare each row's size with the first. To do that, you need to explicitly iterate, using each, map, or some other method.

rampion