Добавить данные неизвестного типа в хэш


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

if val.instance_of?(Hash) then
    @fields.has_key?(key) ? @fields[key].merge!(val) : @fields.merge!({key => val})
elsif val.instance_of?(Array) then
    @fields.has_key?(key) ? @fields[key].push(val) : @fields.merge!({key => Array.new.push(val)})
else
    @fields.has_key?(key) ? @fields[key] << val : @fields.merge!({key => val})
end

Суть метода заключается в том, чтобы взять хэш и вставки значения разных типов, если ключ не существует:

{:ключ = > значение"}, {ключ = ["значение"]}, или {:ключ => {:к => "значение"}}

или добавить, если оно:

{:ключ=> "value1value2"}, {ключ => [["значение1"], ["значение2"]], {:ключ => {:К1 => "значение1", :К2 => "значение2"}}

он работает как задумано, так что мой вопрос, думая, что там, вероятно, более простой способ сделать это.



497
3
задан 5 апреля 2011 в 11:04 Источник Поделиться
Комментарии
2 ответа

Есть несколько вариантов для рефакторинга кода.
В любом случае мы должны получить значение для данного ключа.


  1. Если значение не существует (как и nil по умолчанию в хэш), мы должны установить ценность как значение результата ( стандарт поведения для хэш).

  2. Если существует значение, мы должны сделать что-то на основе существующих или с учетом класса стоимости. ИМХО "делу" оператор очень хорош для этого. В "когда" мы можем установить один или несколько классов, чтобы пересмотреть стандарт поведения.

Код обернут в класс для легкого изучения его в Эсо. Это просто образец для презентации

class MyHash < Hash
def []=(key,val)
super(key,
case (old = self[key]).class
when Array, String
old + val
when Hash, MyHash
old.merge(val)
else
val
end
)
end
end

Ок, сейчас некоторые испытания в IRB:

Строки

 >   mh = MyHash.new()
=> {}

> mh[:k1] = "str1"
=> "str1"

> mh
=> {:k1=>"str1"}

> mh[:k1] = "str2"
=> "str2"

> mh
=> {:k1=>"str1str2"}

Массивы

> mh[:k2] = [1]
=> [1]

> mh
=> {:k1=>"str1str2", :k2=>[1]}

> mh[:k2] = [2]
=> [2]

> mh
=> {:k1=>"str1str2", :k2=>[1, 2]}

Хэши

 > mh[:k3] = {1=>:a}
=> {1=>:a}

> mh
=> {:k1=>"str1str2", :k2=>[1, 2], :k3=>{1=>:a}}

> mh[:k3] = {2=>:b}
=> {2=>:b}

> mh
=> {:k1=>"str1str2", :k2=>[1, 2], :k3=>{1=>:a, 2=>:b}}

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

3
ответ дан 12 апреля 2011 в 10:04 Источник Поделиться

Есть некоторые очевидные цели для рефакторинга, такие как массив.новый.нажимаем(вал) вместо [вал], но для меня весь этот блок кода воняет. Самый очевидный запах - это тип проверки обусловлено отсутствием утиной типизацией.

Можете ли вы подробнее рассказать о той напряженности, которая приведет к этой конструкции? Я подозреваю, что лучшим решением является дальнейший контекст стека, чем то, что вы предоставили.

6
ответ дан 6 апреля 2011 в 06:04 Источник Поделиться