5

我在项目中使用 Struct 而不是简单的 Hash 来为键值对集合提供语义名称。然而,一旦我构建了结构,我需要输出一个哈希值。我在 Ruby 1.9.3 中。例子:

MyMeaninfulName = Struct.new(:alpha, :beta, :gamma) do
  def to_hash
    self.members.inject({}) {|h,m| h[m] = self[m]; h}
  end
end

my_var = MyMeaningfulName.new
my_var.to_hash # -> { :alpha=>nil, :beta=>nil, :gamma=>nil } 

Struct 不包含 to_hash 方法是否有原因?这似乎很自然,但也许有一个根本原因不包括在内。

其次,是否有一种更优雅的方法可以将通用 to_hash 方法构建到 Struct 中(通常是通过猴子补丁,或者通过模块或继承)。

4

4 回答 4

3

我知道问题是关于 ruby​​ 1.9.3,但从 ruby​​ 2.0.0 开始,Struct有一个to_h方法可以完成这项工作。

MyMeaningfulName = Struct.new(:alpha, :beta, :gamma)

my_var = MyMeaningfulName.new
my_var.to_h # -> { :alpha=>nil, :beta=>nil, :gamma=>nil } 
于 2015-02-05T09:51:28.697 回答
2

或这个:

class Struct
  def to_hash
    self.class.members.inject({}) {|h,m| h[m] = self[m]}
  end
end

(注意额外的课程来接触成员)

于 2012-09-06T13:32:17.280 回答
2

不知道为什么,好像很明显。幸运的是,由于它实现了括号运算符,因此您可以在许多地方将其用作哈希。

无论如何,这是相当优雅的:

MyMeaningfulName = Struct.new :alpha, :beta, :gamma do
  def to_hash
    Hash[members.zip values]
  end
end

my_var = MyMeaningfulName.new 1, 2, 3
my_var.to_hash # => {:alpha=>1, :beta=>2, :gamma=>3}
于 2012-09-06T14:50:20.393 回答
0

试试这个:

class Struct
  old_new = self.method(:new)
  def self.new(*args) 
    obj = old_new.call(*args)
    obj.class_exec do
      def to_hash
        self.members.inject({}) {|h,m| h[m] = self[m]; h}
      end
    end
    return obj
  end
end
于 2012-09-06T13:24:50.647 回答