在PHP中,我可以通过设置$variable_name = foo
和echo $$variable_name
之类的内容来动态访问变量,然后echo
foo
的值。但我不清楚如何在Ruby中做到这一点。在PHP中我可以做这样的事情;在数组中分配变量名并迭代它们:
# Set string values.
$value_one = 'a one';
$value_two = 'and a two';
$value_three = 'and a three';
# Set array of variable names.
$process_items_array = array('value_one', 'value_two', 'value_three');
# Roll through the values.
foreach ($process_items_array as $value) {
$$value = do_something($$value) . '<br />';
}
# A simple function for example’s sake.
function do_something ($value = null) {
return strtoupper($value);
}
但是在Ruby中,相同的东西是什么?例如,我尝试了这个,没有一个项目按预期工作;请注意,这是在非类结构中使用self.
引用所指出的伪代码:
# Set string values.
value_one = 'a one';
value_two = 'and a two';
value_three = 'and a three';
# Set array of variable names.
process_items_array = ['value_one', 'value_two', 'value_three']
# Roll through the values.
process_items_array.each { |value|
self.send("#{value}").to_sym = do_something value.try(self.send("#{value}").to_sym)
}
# A simple function for example’s sake.
def do_something value
value = value.try(:strip)
value = nil if value.blank?
value.upcase
end
请注意我尝试使用instance_variable_get
,[send][2]
和to_sym
;我基本上希望有些东西可行,但似乎没什么用。我应该做什么呢?
答案 0 :(得分:2)
您可以使用eval
:
# Set string values.
value_one = 'a one';
value_two = 'and a two';
value_three = 'and a three';
# Set array of variable names.
process_items_array = ['value_one', 'value_two', 'value_three']
# Roll through the values.
process_items_array.each do |variable_name|
# Output value
puts eval(variable_name)
# Reassign variable
new_value = 'foo'
eval("#{variable_name} = new_value")
end
正如评论中所说,您可能希望将数据存储在哈希中。此外,您需要动态创建或读取变量的代码非常糟糕。
答案 1 :(得分:1)
更红宝石的方式(所以没有&#34;危险&#34; eval)
# Set string values.
value_one = 'a one';
value_two = 'and a two';
value_three = 'and a three';
# Set array of variable names.
process_items_array = ['value_one', 'value_two', 'value_three']
# Roll through the values.
process_items_array.each do |variable_name|
# Output value
puts binding.local_variable_get(variable_name.to_sym)
# Reassign variable
binding.local_variable_set(variable_name.to_sym, 'foo')
end
puts value_one, value_two, value_three
# foo
# foo
# foo
答案 2 :(得分:-1)
您可以使用Kernel#binding
获取当前的Binding
对象,然后使用Binding#local_variable_get
和Binding#local_variable_set
来获取和设置本地变量:
# Set string values.
value_one = 'a one';
value_two = 'and a two';
value_three = 'and a three';
# Set array of variable names.
process_items_array = ['value_one', 'value_two', 'value_three']
# Roll through the values.
process_items_array.each { |value|
binding.local_variable_set(value.to_sym, do_something(binding.local_variable_get(value).to_sym)
}
# A simple function for example’s sake.
def do_something value
value = value.try(:strip)
value = nil if value.blank?
value.upcase
end
# Show that it works:
p value_one, value_two, value_three
# "A ONE"
# "AND A TWO"
# "AND A THREE"
但是,该代码有点不合时宜:
Symbol
来表示变量名称,而不是String
s do
/ end
代替{
/ }
进行多行副作用foo_array
)您必须在使用之前移动do_something
的定义,否则您会获得NoMethodError
。
为了更容易重复,我删除了对active_support
的依赖,因此尝试测试的人不必安装额外的宝石,甚至不需要再现解决方案
这将是一个更惯用的代码版本:
# Set string values.
value_one = 'a one'
value_two = 'and a two'
value_three = 'and a three'
# Set array of variable names.
items_to_process = %i[value_one value_two value_three]
# A simple method for example’s sake.
def do_something(value)
value.upcase
end
b = binding
# Roll through the values.
items_to_process.each do |var|
b.local_variable_set(var, do_something(b.local_variable_get(var)))
end
# Show that it works:
p value_one, value_two, value_three
# "A ONE"
# "AND A TWO"
# "AND A THREE"