51

Rubyでハッシュを構造体に変換するにはどうすればよいですか?

これを考えると:

h = { :a => 1, :b => 2 }

次のような構造体が必要です。

s.a == 1
s.b == 2
4

12 に答える 12

71

すでに構造体が定義されていて、インスタンスをハッシュでインスタンス化したい場合:

Person = Struct.new(:first_name, :last_name, :age)

person_hash = { first_name: "Foo", last_name: "Bar", age: 29 }

person = Person.new(*person_hash.values_at(*Person.members))

=> #<struct Person first_name="Foo", last_name="Bar", age=29>
于 2014-09-30T23:22:54.130 に答える
70

特にである必要がなくStruct、代わりに である場合OpenStruct:

pry(main)> require 'ostruct'
pry(main)> s = OpenStruct.new(h)
=> #<OpenStruct a=1, b=2>
pry(main)> puts s.a, s.b
1
2
于 2012-08-14T23:38:39.440 に答える
54

Ruby 1.9以降ではハッシュキーの順序が保証されているため:

Struct.new(*h.keys).new(*h.values)
于 2012-08-14T23:59:57.743 に答える
10

以下は、信頼できる方法でハッシュから構造体を作成します (Ruby ではハッシュの順序が保証されていないため)。

s = Struct.new(*(k = h.keys)).new(*h.values_at(*k))
于 2012-08-14T23:16:44.167 に答える
1

値を構造体の適切な順序にマップする例を次に示します。

require 'securerandom'

Message = Struct.new(:to, :from, :message, :invitee)

message_params = {from: "my@email.address", to: "your@email.address",
        invitee: SecureRandom.uuid, message: "hello"}

if Message.members.sort == message_params.keys.sort
  # Do something with the return struct object here
  Message.new *Message.members.map {|k| message_params[k] } 
else
  raise "Invalid keys for Message"
end
于 2014-09-23T17:37:19.513 に答える
0

次のコードを使用して、ハッシュから構造体に変換できます。

Struct.new(*my_hash.keys.map(&:to_sym)).new(*my_hash.values)

文字列キーでエラーが発生するため、すべてのキーをシンボルに変換してください。NameError: identifier my_key needs to be constant

これは非常に強力なアクションであるため、個人的には Hash クラスにモンキー パッチを追加することをお勧めします。

# config/initializers/core_extensions.rb

Hash.class_eval do
  def to_struct
    Struct.new(*keys.map(&:to_sym)).new(*values)
  end
end
于 2020-12-02T22:06:51.727 に答える