【问题标题】:Setting variables with blocks in ruby在 ruby​​ 中使用块设置变量
【发布时间】:2009-12-01 23:14:13
【问题描述】:

我发现自己在 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 中是否有一种“简洁”的方式来设置带有块的变量?

【问题讨论】:

  • 我想每个人都没有抓住重点。我也一直想知道这一点,还有其他几种语言可以做到这一点,即 perl 的 $_。使用 $_

标签: ruby idioms


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    我首先想到的是:

    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'
    

    【讨论】:

    • 酷,我不记得没有参数的版本,但块是这样工作的。
    • 这个解决方案比 Phil Ross 建议的解决方案有优势吗?他更适合我的应用程序,但如果性能开销很大,我也可以使用它。
    • 不,我第一次尝试注入很有趣,但太复杂了,不是您立即需要的。我认为我的最后一行是您想要的,只是因为它稍微简单一些。我们已经习惯了用块解决问题(包括我在内的每个人),我们可能会忽略一个简单到只需要*#join 的问题。 :-)
    【解决方案3】:

    您似乎没有在循环中访问zip,因此以下应该可以工作:

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

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

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

    【讨论】:

    • 您的第一个解决方案在我的应用程序中最有意义,我需要保留 zips 数组,但根据它的长度创建一个字符串。顺便说一下,这是一个 MySQL 查询
    【解决方案4】:

    尽管其他人针对您的具体问题给出了更惯用的解决方案,但实际上有一个很酷的方法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 的 $_ 那样普遍涵盖所有内容,但它允许您将方法隐式发送到单个对象。

    【讨论】:

      【解决方案5】:

      在 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"
      

      【讨论】:

        猜你喜欢
        • 2016-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多