2012-11-14 18 views
13

說我有這個散列:哈希到本地變量裏面紅寶石反過來值

entry = {"director"=>"Chris Nolan", "prducer"=>"Sum Duk", "writer"=>"Saad Bakk"} 

我想相關的值來提取每個鍵進入自己的局部變量:

director = "Chris Nolan" 
producer = "Sum Duk" 
... 

通過使用一個循環而不是:

director = entry["director"] 

由於有很多值,我不想單獨做它們。

我發現這幾乎完美的工作,除了它創建一個實例變量,我想要一個局部變量,但local_variable_set因爲某些原因不存在。

entry.each_pair { |k, v| instance_variable_set("@#{k}", v) } 

有沒有解決方法?或者失敗了,一種將實例變量轉換爲本地變量的方法,並且可以在不逐一刪除實例的情況下進行刪除?

+0

任何原因,他們不能留在哈希中,並從那裏訪問?據推測,你以後使用了局部變量 - 是不是很容易使用哈希值? – Pavling

+0

如果您使用的是Rails(或者僅僅是ActiveSupport),您可以使用下面的一行:'director,producer,writer = entry.values_at('director','producer','writer')'。不幸的是,你必須輸入每個變量名兩次(而不是你要求的零次),但它仍然是我發現的最簡潔的方法。 – antinome

+0

可能重複的[如何動態創建局部變量?](http://stackoverflow.com/questions/18552891/how-to-dynamically-create-a-local-variable) – Ajedi32

回答

2

由於變量的作用域,您不能創建局部變量。
如果您在塊內創建局部變量,則該變量只能在塊本身內訪問。
請參閱此問題以獲取更多信息。
Dynamically set local variables in Ruby

+0

這是有道理的,但是很傷心。我想我被卡住了使用實例變量或手動執行:( – kakubei

+0

的確如此,我想在代碼中犧牲一些行是最好的選擇 – MurifoX

4

你可以用eval做到這一點,但在這些變量上的所有操作必須在範圍內,他們在被定義

例如,這將工作:

vals = { 
    "foo" => "bar", 
    "baz" => "qux" 
} 

eval <<-EOF 
    #{ vals.map {|k, v| "#{k} = \"#{v}\""}.join("\n") } 
    puts foo 
EOF 

然而,這不會:

vals = { 
    "foo" => "bar", 
    "baz" => "qux" 
} 

eval <<-EOF 
    #{ vals.map {|k, v| "#{k} = \"#{v}\""}.join("\n") } 
EOF 

puts foo 

as foo超出範圍在t他結束了評估。但是,如果您在變量的所有工作都可以在eval的範圍內完成,那麼這是非常可行的。

+0

@kakubei:的確,在Ruby中,你幾乎可以突破任何限制。儘管你選擇的是局部變量 - 有點困難,但局部變量只適用於小時間使用。 –

+0

對於使用非字符串(或可串行)鍵的散列並不適用。 – Hut8

2

選項1

我不建議這只是好玩,但它主要是有你後的效果:

entry.each |k, v| 
    singleton_class.send(:attr_accessor, k) 
    send("#{k}=", v) 
end 

director      # => "Chris Nolan" 
self.director = "Wes Anderson" # Unfortunately, must use self for assignment 
director      # => "Wes Anderson" 

而不是創造局部變量它定義在acccessor方法當前對象的單例類,您可以調用它們,就好像它們是局部變量一樣。

爲了使它們更「本地」,您可以使用singleton_class.remove_method刪除這些方法,當你完成它們。你甚至可以試着用相同的名字別名任何現有的singleton類方法,然後恢復它們。

選項2

這是我在實際代碼中使用。它需要Ruby On Rails附帶的ActiveSupport gem,但也可以單獨使用。

director, producer, writer = entry.values_at('director', 'producer', 'writer') 

不幸的是它需要你要求鍵入每個變量名稱兩次,而不是零次。如果你看準了哈希值的順序,你可以寫:

director, producer, writer = entry.values # Not so good, IMO. 

我感到不安這個版本,因爲現在創建的哈希代碼有一個不明顯的責任,以確保哈希按照一定的順序。

注意

如果你的目標只是爲了降低打字,這裏是一種方法,只需要每個變量的訪問兩個人物比,如果他們是真正的局部變量:

e = OpenStruct.new(entry) 
e.director  # => "Chris Nolan"