2012-08-14 26 views
37

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

この与えられた:(ハッシュ順序はRubyで保証されていないので)、次は信頼性の高い方法でハッシュから構造体を作成し

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

答えて

49

それは特に時間ない場合AVE 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 
+0

以前はOpenStructについて聞いたことがありませんでした。それはとても涼しいです!ありがとう! – alf

+5

OpenStructsの使用が非常に遅くなることに注意してください。少数の小さなオブジェクトでは罰金がかかりますが、縮尺はひどくなります。 さらに詳しい情報はこちら @stackoverflow.com/questions/1177594/ruby-struct-vs-openstruct –

+0

@AFaderDarkly @AFaderDarklyスピードの問題については十分に文書化されていますが、感謝しています。 –

8

:私は、このようなことを構造体にしたい

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

を:

s = Struct.new(*(k = h.keys)).new(*h.values_at(*k)) 
45

ハッシュキーの順序は、ルビー1.9+で保証されているので:ここ

Struct.new(*h.keys).new(*h.values) 
+0

お役立ち情報私はどこかでそれを読むが、どこを覚えていない。ありがとう! – alf

+0

これは(少なくともRuby 2.2.0では)動作していないようです: 'Struct.new(* h.keys)'が呼び出されました: 'NameError:識別子my_keyが定数である必要があります' – Joe

+2

@Joeうまくいきます。私はあなたのハッシュのためにエラーの原因となる文字列キーを使用したと思います。エラーは、文字列ではなくシンボルという、一定の値が必要であることを伝えています。私は2.1.5でエラーを再現することができます、私はシンボルに切り替えると遠ざかります。 – ehsanul

1

はの適切な順序に値をマッピングする例を示します構造体:

require 'securerandom' 

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

message_params = {from: "[email protected]", to: "[email protected]", 
     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 
52

あなたは既に定義構造体を持っている、とあなたはハッシュでインスタンスを生成する場合:

を持つ
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> 
+0

これは受け入れられた答えであるはずです:)。ありがとう! – Ven

+0

ありがとう!私は、コマンドまたは外部コードから呼び出すことができる宝石を設計しています。それぞれオプションを提供しています(それぞれOptionParserまたはHashを使用しています)。これは、私の宝石の初期化中にオプションの簡単なフィルタリングを可能にします。構造体は許可されたオプションも "self-document"するのに役立ちます! – Excalibur

-1
require 'ds_hash' 

data = {a: {b: 123 }}.to_struct 

data.a.b == 123  # true 
data.a == {b: 123 } # true 
2

非常に実用的である:

class Hash 
    def to_struct 
    Struct.new(*keys).new(*values) 
    end 
end 

そして、いくつかの例:

配列で動作します
>> { a: 1, b: 2 }.to_struct 
=> #<struct a=1, b=2> 
>> { a: 1, b: 2 }.to_struct.a 
=> 1 
>> { a: 1, b: 2 }.to_struct.b 
=> 2 
>> { a: 1, b: 2 }.to_struct.c 
NoMethodError: undefined method `c` for #<struct a=1, b=2> 

ディープto_struct

class Array 
    def to_struct 
    map { |value| value.respond_to?(:to_struct) ? value.to_struct : value } 
    end 
end 

class Hash 
    def to_struct 
    Struct.new(*keys).new(*values.to_struct) 
    end 
end 
+0

その良いですが、そのjsonハッシュ '['name']'がキーを象徴する必要がある場合。 – 7urkm3n

関連する問題