Самый элегантный способ проверить равенство размеров подмассивов в многомерном массиве?

(Можете ли вы сказать, что я изучаю Ruby сегодня? :))

Я хочу определить, является ли многомерный массив, с которым я работаю, «прямоугольником», то есть строки имеют одинаковый размер. Вот что я делаю, что работает, но кажется неуклюжим.

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

По сути, я проверяю, равен ли размер первого массива размеру всего другого массива. Почему-то кажется, что это недостаточно "рубиновый", понимаете? У кого-нибудь есть более изящные решения?


person miketaylr    schedule 14.02.2009    source источник


Ответы (3)


Пытаться:

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

См. http://www.ruby-doc.org/core/classes/Array.html (оператор []) и http://www.ruby-doc.org/core/classes/Enumerable.html (метод any?)

person vladr    schedule 14.02.2009

Это не приведет к ошибке:

@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

Это вызовет ошибку:

@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

Этот код перебирает все подмассивы внутри массива и проверяет, не совпадает ли размер их строки с размером первой, а затем выдает ошибку, если это так.

person Ryan Bigg    schedule 14.02.2009

Я мог бы сделать что-то вроде того, что опубликовали другие, или

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

Вы должны заметить, что ваш пример кода не делает того, что вы думаете.

# 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

Таким образом, ваш оператор if фактически сравнил размер строки с размером столбца (плюс 1, поскольку он был от 0 до @myArray.size включительно). Он не сравнивал размер каждой строки с первой. Для этого вам нужно явно выполнить итерацию, используя каждый, карту или какой-либо другой метод.

person rampion    schedule 14.02.2009
comment
Вы также можете использовать @myArray.map(&:size).uniq.one? Метод Enumerable#one? был представлен в Ruby 1.8.7. - person Andrew Grimm; 28.09.2011