2012-08-14 81 views
37

如何將散列轉換爲Ruby中的結構?將散列轉換爲結構

鑑於此:

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

我想一個結構使得:

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

回答

49

如果沒有專門^h 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 2012-08-14 23:51:02

+5

請注意OpenStructs的使用速度非常慢。適合少數小物體,但尺寸很差。 一些進一步的信息在這裏: http://stackoverflow.com/questions/1177594/ruby-struct-vs-openstruct – 2014-02-22 22:21:51

+0

@AFaderDarkly我認爲他們的速度問題是有據可查的,但謝謝。 – 2014-02-22 23:15:01

8

下面創建從一個可靠的方式散列一個結構(因爲哈希順序沒有紅寶石保證) :

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

由於散列鍵順序在紅寶石1.9+保證:

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

很高興知道。儘管我在某個地方看過,但沒有記得在哪裏。謝謝! – alf 2012-08-15 00:56:11

+0

這看起來不起作用(至少在Ruby 2.2.0中):'Struct.new(* h.keys)'提出:'NameError:標識符my_key需要保持不變' – Joe 2015-08-19 17:22:20

+2

@Joe它確實工作正常。我認爲你使用了字符串鍵爲你的哈希,這是錯誤的原因。錯誤告訴你它需要一個常量值,即一個符號而不是一個字符串。我可以重寫2.1.5中的錯誤,如果我切換到符號,就會消失。 – ehsanul 2015-09-14 22:10:31

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 2014-11-26 15:55:04

+0

謝謝!我正在設計一個可以從命令或外部代碼調用的gem,每個提供選項(分別使用OptionParser或Hash)。這可以在初始化我的寶石時輕鬆過濾選項。 Struct還有助於「自我記錄」允許的選項! – Excalibur 2015-12-12 20:00:13

-1
require 'ds_hash' 

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

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

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> 

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 2018-01-31 10:58:51