Ruby: элегантная инициализация массива и возврат в Ruby - PullRequest
6 голосов
/ 05 декабря 2011

У меня есть метод:

def deltas_to_board_locations(deltas, x, y)
    board_coords = []
    deltas.each_slice(2) do |slice|
      board_coords << x + slice[0] 
      board_coords << y + slice[1]
    end
    board_coords
  end 

где deltas - это массив, а x, y - фиксированные числа.

Есть ли способ исключить первую и последнюю строку, чтобы сделатьметод более элегантный?

Как:

def deltas_to_board_locations(deltas, x, y)
    deltas.each_slice(2) do |slice|
      board_coords << x + slice[0] 
      board_coords << y + slice[1]
    end
  end 

Ответы [ 3 ]

7 голосов
/ 05 декабря 2011
deltas.each_slice(2).flat_map do |dx, dy|
  [x + dx, y + dy]
end
6 голосов
/ 05 декабря 2011
deltas.each_with_index.map { |val, idx| val + (idx % 2 == 0 ? x : y )}

Является ли это "менее сложным", зависит от аудитории.


Уменьшение дублирования и сложности должно быть сосредоточено на макро-поведении, а не на микрорефакторинге коротких, уже читаемых методов.

Приведет ли это переписывание к количественно более легкой для понимания системе? Или есть более важные проблемы более высокого уровня?

Будет ли лучше улучшить документацию по приложениям, классам и методам? Должны ли эти документы быть в коде или в вики? Будет ли картинка стоить тысячу строк?


Сравнение производительности с @ tokland's (его выигрывает значительная сумма). Предполагая, deltas является массивом из миллиона элементов 1-1m. МРТ, Ubuntu, старая машина для обработки ключей.

Моя версия

deltas.each_with_index.map { |val, idx| val + (idx % 2 == 0 ? x : y )}

Total: 1.764807

 %self     total     self     wait    child    calls  name
100.00      1.76     1.76     0.00     0.00        1  Array#each
  0.00      1.76     0.00     0.00     1.76        1  Global#[No method]
  0.00      1.76     0.00     0.00     1.76        2  Enumerable#each_with_index
  0.00      1.76     0.00     0.00     1.76        1  Enumerable#map
  0.00      1.76     0.00     0.00     1.76        1  Enumerator#each

Лучшая, короткая, более коммуникативная версия

deltas.each_slice(2).flat_map { |dx, dy| [x + dx, y + dy] }

Total: 1.236144

 %self     total     self     wait    child    calls  name
100.00      1.24     1.24     0.00     0.00        1  Array#each
  0.00      1.24     0.00     0.00     1.24        1  Global#[No method]
  0.00      1.24     0.00     0.00     1.24        2  Enumerable#each_slice
  0.00      1.24     0.00     0.00     1.24        1  Enumerable#flat_map
  0.00      1.24     0.00     0.00     1.24        1  Enumerator#each

Оригинальная версия (самая быстрая):

Total: 0.899122

 %self     total     self     wait    child    calls  name
100.00      0.90     0.90     0.00     0.00        1  Array#each
  0.00      0.90     0.00     0.00     0.90        1  Global#[No method]
  0.00      0.90     0.00     0.00     0.90        1  Enumerable#each_slice
4 голосов
/ 05 декабря 2011
deltas.each_slice(2).flat_map { |dx, dy|
  [x + dx, y + dy]
}

Вышеописанное работает для Ruby 1.9, но я согласен с Renaud. Очевидное решение должно быть предпочтительным, и в этом случае оно быстрее моего.

Редактировать : Включены комментарии @ tokland.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...