2011-04-21 90 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