如何将哈希转换为ruby中的结构?
鉴于这种:
h = { :a => 1, :b => 2 }
Run Code Online (Sandbox Code Playgroud)
我想要一个结构,这样:
s.a == 1
s.b == 2
Run Code Online (Sandbox Code Playgroud)
ela*_*ado 67
如果已经定义了结构,并且希望使用哈希实例化实例:
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>
Run Code Online (Sandbox Code Playgroud)
Dav*_*ton 60
如果它没有特别必须是a 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
Run Code Online (Sandbox Code Playgroud)
Phr*_*ogz 51
由于Ruby 1.9+中保证了Hash键顺序:
Struct.new(*h.keys).new(*h.values)
Run Code Online (Sandbox Code Playgroud)
这是基于@elado 上面的回答,但使用keyword_init值(结构文档)
你可以简单地这样做:
Person = Struct.new(:first_name, :last_name, :age, keyword_init: true)
person_hash = { first_name: "Foo", last_name: "Bar", age: 29 }
person = Person.new(person_hash)
=> #<struct Person first_name="Foo", last_name="Bar", age=29>
Run Code Online (Sandbox Code Playgroud)
以下以可靠的方式从哈希创建结构(因为在ruby中不保证哈希顺序):
s = Struct.new(*(k = h.keys)).new(*h.values_at(*k))
Run Code Online (Sandbox Code Playgroud)
有Hash#to_struct很实用:
class Hash
def to_struct
Struct.new(*keys).new(*values)
end
end
Run Code Online (Sandbox Code Playgroud)
还有一些例子:
>> { 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>
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)