Переписывание «лучшего» кода - PullRequest
5 голосов
/ 18 июня 2011

Я использую Ruby 1.9, и я хотел бы знать, есть ли "лучший" способ написать следующий код.

  array_one = []
  array_two = []
  some_array.each { |value|
    array_one << value.id
    array_two << value.name
  }

Мне «не нравится» инициализировать array_one и array_two, как в приведенном выше примере, а затем добавить в них value.id и value.name. Это потому, что, в основном, для лучшего понимания и чтения кода в моем приложении.

Я хотел бы предоставить ту же функциональность, но с "лучшим" кодированием.Возможно ли это?

Ответы [ 3 ]

5 голосов
/ 18 июня 2011

Кодовый шаблон, который у вас есть, обычно является верным признаком fold (или, в более общем случае, катаморфизма ), желающего выйти.Ruby предоставляет встроенный метод сворачивания, по историческим причинам он называется inject.

Непроверенный:

array_one, array_two = some_array.
  inject([[], []]) {|(array_one, array_two), value|
    [array_one << value.id, array_two << value.name]
}

Не уверен, считаете ли вы, что это «лучше» или нет,Для тех, кто понимает, что такое fold, это, вероятно, более понятно.Для тех, кто этого не делает, вероятно, нет.

(хотя я думаю, что если вы не не понимаете, что такое fold, то вы не очень хороший программист на Rubyили даже очень хороший программист на всех , но это только мое мнение.)

Однако говорить, что некоторая итерация является fold, на самом деле не очень полезно, так как fold - это общий метод итерации (это означает, что каждая форма итерации может быть выражена как fold).* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Г}Однако, если у вас нет надежных тестов и результатов профилирования, которые показывают, что этот двойной обход является основным источником проблем с производительностью в вашем приложении, вам действительно не стоит об этом беспокоиться.

1 голос
/ 18 июня 2011

Вы можете использовать transpose для преобразования массива из n элементов, содержащего двухэлементные массивы, в два массива из n элементов:

array_one, array_two = some_array.map {|value| [value.id, value.name]}.transpose

Вот ссылка RDoc , хотя она довольно краткая.

1 голос
/ 18 июня 2011

Вы можете использовать метод Array # collect :

array_one = some_array.collect { |value| value.id }
array_two = some_array.collect { |value| value.name }

Как отметил в своем ответе Йорг В. Миттаг, это решение также дважды обойдет исходный массив.

...