使用ruby中的块设置变量

时间:2009-12-01 23:14:14

标签: ruby idioms

我发现自己在Ruby中使用类似PHP的循环,当语言的其余部分如此整洁时,感觉不对。我结束了这样的代码:

conditions_string = ''

zips.each_with_index do |zip, i|

    conditions_string << ' OR ' if i > 0
    conditions_string << "npa = ?"

end

# Now I can do something with conditions string

我觉得我应该可以做这样的事情

conditions_string = zips.each_with_index do |zip, i|

    << ' OR ' if i > 0
    << "npa = ?"

end

在Ruby中使用块设置变量是否有'整洁'的方式?

5 个答案:

答案 0 :(得分:4)

我想到的第一件事是:

a = %w{array of strings}             => ["array", "of", "strings"]
a.inject { |m,s| m + ' OR ' + s }    => "array OR of OR strings"

但这可以通过

来完成
a.join ' OR '

虽然我认为你很快就需要这个结构,但是为了复制你的确切例子,我可能会使用:

([' npa = ? '] * a.size).join 'OR'

答案 1 :(得分:4)

由于你实际上没有使用zip的值,我建议

zips.map {|zip| "npa = ?" }.join(" OR ")

但总的来说,我建议查看Enumerable#inject函数来避免这种循环。

答案 2 :(得分:1)

您似乎没有在循环中访问zip,因此以下内容应该有效:

conditions_string = (['npa = ?'] * zips.length).join(' OR ')

如果您需要访问zip,则可以使用:

conditions_string = zips.collect {|zip| 'npa = ?'}.join(' OR ')

答案 3 :(得分:1)

虽然其他人已经为您的特定问题提供了更多惯用解决方案,但实际上有一种很酷的方法Object#instance_eval,这是许多Ruby DSL使用的标准技巧。它将self设置为其块内instance_eval的接收者:

简短的例子:

x = ''
x.instance_eval do
    for word in %w(this is a list of words)
        self << word  # This means ``x << word''
    end
end
p x
# => "thisisalistofwords"

它并不像Perl $_那样普遍覆盖所有内容,但它允许您隐式地将方法发送到一个对象。

答案 4 :(得分:0)

在1.8.7+中,您可以使用each_with_object

它取代了DigitalRoss的'注入'习语:

a = %w{hello my friend}  => ["hello", "my", "friend"]
a.each_with_object("") { |v, o| o << v << " NOT " }  => "hello NOT my NOT friend NOT"