Thursday, March 31, 2011

Most elegant way to check for equality in size of sub-arrays in multidimensional array?

(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[0..@myArray.size].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?

From stackoverflow
  • 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.

    miketaylr : OOh. nice one. :)
  • 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.

  • 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.

0 comments:

Post a Comment