【问题标题】:replacing lines in ruby string替换红宝石字符串中的行
【发布时间】:2011-12-02 03:35:26
【问题描述】:

我正在尝试使用 each_line 方法遍历包含多行的 Ruby 字符串,但我也想更改它们。我正在使用以下代码,但它似乎不起作用:

string.each_line{|line| line=change_line(line)}

我想,Ruby 发送的是我的行的副本,而不是行本身,但不幸的是没有方法 each_line!。我也试过gsub!方法,使用 /^.*$/ 来检测每一行,但似乎它只调用 change_line 方法并用它替换所有行。任何想法如何做到这一点? 在此先感谢:)

【问题讨论】:

    标签: ruby


    【解决方案1】:

    @azlisum:您没有存储连接的结果。使用:

    output = string.lines.map{|line|change_line(line)}.join
    

    比较四种方式在字符串中逐行处理:

    # Inject method (proposed by @steenslang)
    output = string.each_line.inject(""){|s, line| s << change_line(line)}
    
    # Join method (proposed by @Lars Haugseth)
    output = string.lines.map{|line|change_line(line)}.join
    
    # REGEX method (proposed by @olistik)
    output = string.gsub!(/^(.*)$/) {|line| change_line(line)}
    
    # String concatenation += method (proposed by @Erik Hinton)
    output = "" 
    string.each_line{|line| output += change_line(line)}                   
    

    Benchmark 的时机:

                       user     system      total        real
    Inject Time:   7.920000   0.010000   7.930000 (  7.920128)
    Join Time:     7.150000   0.010000   7.160000 (  7.155957)
    REGEX Time:   11.660000   0.010000  11.670000 ( 11.661059)
    += Time:       7.080000   0.010000   7.090000 (  7.076423)
    

    正如@steenslag 指出的那样,'s += a' 将生成new string for each concatenation,因此通常不是最佳选择。

    因此,考虑到时间,你最好的选择是:

    output = string.lines.map{|line|change_line(line)}.join
    

    另外,恕我直言,这是看起来更干净的选择。

    备注:
    Using Benchmark
    Ruby-Doc: Benchmark

    【讨论】:

      【解决方案2】:

      你也应该尝试从一个空白字符串开始,每个字符串遍历字符串,然后将结果推送到空白字符串。

      output = "" 
      string.each_line{|line| output += change_line(line)}
      

      在你原来的例子中,你是对的。您的更改正在发生,但它们并未在任何地方保存。 Ruby 中的Each 默认情况下不会更改任何内容。

      【讨论】:

      【解决方案3】:

      你可以使用 gsub!向它传递一个块:

      string.gsub!(/^(.*)$/) {|line| change_line(line)}
      

      来源:String#gsub!

      【讨论】:

        【解决方案4】:

        String#each_line 用于读取字符串中的行,而不是写入它们。您可以使用它来获得您想要的结果:

        changed_string = ""
        string.each_line{ |line| changed_string += change_line(line) }
        

        【讨论】:

          【解决方案5】:

          如果你不给 each_line 一个块,你会得到一个枚举器,它有注入方法。

          str = <<HERE
          smestring dsfg
          line 2
          HERE
          
          res = str.each_line.inject(""){|m,line|m << line.upcase}
          

          【讨论】:

            猜你喜欢
            • 2013-12-28
            • 2019-10-23
            • 2010-11-29
            • 1970-01-01
            • 1970-01-01
            • 2014-02-11
            • 2011-01-21
            • 2022-01-21
            • 2010-09-25
            相关资源
            最近更新 更多