2011-04-21 93 views
0

Ruby似乎是一種特別適合解決此問題的語言,但我沒有找到一種優雅的方式來實現它。我想是會接受的值,並將其添加到哈希像這樣,與如果鍵已經存在,它是如何添加特定需求的方法:將未知類型的數據添加到散列表

添加「富」到:KEY1

{:key1 => 'foo'} 

添加 '欄' 來:KEY1

{:key1=> 'foobar'} 

添加[ '富']到:KEY2

{:key2 = ['foo']} 

添加['BA R']到:KEY2

{:key2 => [['foo'], ['bar']] 

加入{:K1 => '富'}到:KEY3

{:key3 => {:k1 => 'foo'}} 

加入{:K2 => '酒吧'}到:KEY3

{:key3 => {:k1 => 'foo', :k2 => 'bar'}} 

現在我可以做到這一點,但它看起來馬虎,而不是像慣用的Ruby。什麼是這樣做的好方法?

+2

我不能說我完全相信你正試圖在這裏做的,但爲什麼不陣列部分' {:key2 => ['foo','bar']}'? – 2011-04-21 15:43:05

+0

如果你剛剛在#Hash上定義了#來做#merge,你可以使用它。 def add(h,k,v); h [k]? h [k] + = v:h [k] = v; end – 2011-04-21 15:52:25

+0

這不是一個好例子,但我只是表明它必須是一個數組數組。 – 2011-04-21 16:04:46

回答

4

爲了讓它更像Ruby,你可能想要擴展Hash類來提供這種功能,或者爲了這個特定的目的創建你自己的子類。例如:

class FancyHash < Hash 
    def add(key, value) 
    case (self[key]) 
    when nil 
     self[key] = value 
    when Array 
     self[key] = [ self[key], value ] 
    when Hash 
     self[key].merge!(value) 
    else 
     raise "Adding value to unsupported #{self[key].class} structure" 
    end 
    end 
end 

這將取決於什麼「並稱」你的方式詮釋準確,因爲你的例子似乎有些簡單化,並且沒有解決,當你添加一個哈希預先存在的陣列會發生什麼,除其他事項外。

這個想法是,你定義了一個處理程序,可以容納儘可能多的可能性,如果你不能管理,拋出一個異常。

+0

這些例子可能過於簡單,但都是我的要求所需要的。順便說一句,它是關閉的話題,但如果你正在擴展內置類,這將在Rails項目中去哪裏? – 2011-04-21 15:57:20

+1

你通常會把它們放在你的lib目錄中。 – 2011-04-21 16:16:59

+1

實際上最終把它放在我的config/initializers目錄中。在我的任何代碼加載之前需要加載它嗎? – 2011-04-21 16:23:52

0

如果你想使用OOP的多態功能,您可能想要做的:

class Object; def add_value v; v end end 
class String; def add_value v; self+v end end # or concat(v) for destructive 
class Array; def add_value v; [self, v] end end # or replace([self.dup, v]) for destructive 
class Hash; def add_value v; merge(v) end end # or merge!(v) for destructive 

class Hash 
    def add k, v; self[k] = self[k].add_value(v) end 
end