将未知类型的数据添加到哈希

时间:2011-04-21 15:36:36

标签: ruby-on-rails ruby

Ruby似乎是一种特别适合解决这个问题的语言,但我找不到一种优雅的方法来实现它。我想要的是一个接受一个值并将其添加到类似哈希的方法,如果密钥已经存在,具有如何添加它的特定要求:

将'foo'添加到:key1

{:key1 => 'foo'}

将“bar”添加到:key1

{:key1=> 'foobar'}

将['foo']添加到:key2

{:key2 = ['foo']}

将['bar']添加到:key2

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

添加{:k1 => 'foo'} to:key3

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

添加{:k2 => 'bar'} to:key3

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

现在我可以做到这一点,但它看起来很草率,不像惯用的Ruby。有什么好办法呢?

2 个答案:

答案 0 :(得分: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

这将取决于您对“添加”含义的确切解释,因为您的示例看起来有些简单,并且没有解决在向预先存在的数组添加哈希时发生的事情等等。

这个想法是你定义一个处理器,它可以容纳尽可能多的可能性,如果你不能管理就抛出异常。

答案 1 :(得分: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