Как мне избавиться от дублирования в ruby при использовании clone?

#ruby #refactoring

#ruby #рефакторинг

Вопрос:

Этот метод просто изменяет идентификатор для любого найденного player_id. Вонючка ненавидит это, но я не могу найти способ провести его осмысленный рефакторинг.

 (1..9).each { |n|
    n = n.to_s
    self.player_ids[n] = self.site_id.clone << "_" << self.player_ids[n].clone if self.player_ids[n]        
}
  

Должен ли я просто жить с этим дублированием, потому что функция clone не позволяет мне:

 player_id = self.player_ids[n]
player_id = self.site_id.clone << "_" << player_id.clone if player_id
  

Пример ввода:

 {:player_ids => {"2" => "player_name1", "6" => "player_name4", "9" => "player_name9"}
  

вывод:

 {:player_ids => {"2" => "PRE_player_name1", "6" => "PRE_player_name4", "9" => "PRE_player_name9"}
  

Комментарии:

1. Можете ли вы попробовать self.site_id "_" self.player_ids[n] if self.player_ids[n] ?

2. Это клонирование и установка на место выглядит довольно плохо. Вы уверены, что хотите этого? почему бы вам не показать нам одну (или более) пару input / desired_output, чтобы мы могли понять, чего вы хотите.

3. Извините, я должен выработать привычку показывать входные и выходные данные.

4. Вы уверены, что хотите использовать player_ids в качестве ключа внутри хэша, а не быть назначенным хэшу? В вашем примере не сказано, что он сам по себе является хэшем, поэтому player_ids[n] не имеет смысла.

Ответ №1:

Вот два возможных метода, основанных на вашем примере ввода и вывода:

 site_id = 'PRE'
prefix  = "#{site_id}_"
h = {:player_ids => {"2" => "player_name1", "6" => "player_name4", "9" => "player_name9"}}

# If mutating the original hash is not OK
h2 = h.dup
h2[:player_ids] = Hash[ h[:player_ids].map{ |s,n| [s, n.sub(/^/,prefix)] } ]
p h, h2
#=> {:player_ids=>{"2"=>"player_name1", "6"=>"player_name4", "9"=>"player_name9"}}
#=> {:player_ids=>{"2"=>"PRE_player_name1", "6"=>"PRE_player_name4", "9"=>"PRE_player_name9"}}

# If mutating the original hash is OK
h[:player_ids].each{ |id_string,name| name.sub! /^/, prefix }
p h
#=> {:player_ids=>{"2"=>"PRE_player_name1", "6"=>"PRE_player_name4", "9"=>"PRE_player_name9"}}
  

Если это не то, что вы хотите, пожалуйста, отредактируйте пример ввода / вывода вашего вопроса и оставьте комментарий, разъясняющий ваши потребности.

Комментарии:

1. Спасибо! Если site_id = «PRE», есть ли лучший способ добавить его в подраздел, чем site_id.clone << «_»? Metric, похоже, ненавидит мое частое использование clone.

2. @JeremySmith Я отредактировал ответ, чтобы включить site_id в качестве переменной.

Ответ №2:

#clone требуется только потому, что вы используете операции изменения ( << ) над строкой. Использование интерполяции строк предотвращает ненужное клонирование, а также делает ваш код более идиоматичным.

 player_ids[n] amp;amp;= "#{site_id.clone}_#{player_ids[n]}"
  

В качестве бонуса я удалил ваши ненужные ссылки на self и заменил ваше if на and-equals.