Подтвердить что ты не робот

Преобразовать хэш в структуру

Как преобразовать хэш в структуру в ruby?

Учитывая это:

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

Мне нужна такая структура, что:

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

Ответ 1

Если это не обязательно должно быть 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

Ответ 2

Если у вас уже определена структура, и вы хотите создать экземпляр экземпляра с хешем:

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>

Ответ 3

Так как порядок ключей Hash гарантирован в Ruby 1.9 +:

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

Ответ 4

Следующее создает структуру из хэша надежным способом (поскольку хэш-порядок не гарантируется в ruby):

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

Ответ 5

Имея Hash#to_struct вполне практично:

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>

Deep 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

Ответ 6

Здесь приведен пример сопоставления значений с правильным порядком Struct:

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

Ответ 7

require 'ds_hash'

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

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