【问题标题】:Concatenate two multi-line strings line-by-line逐行连接两个多行字符串
【发布时间】:2016-10-13 06:18:36
【问题描述】:

我有两个多行字符串(代表ASCII charts)。我想将它们连接起来,使它们并排。

例如:

s1 = "aaaa
a
aaaa"
s2 = "bbb
bbbb"
puts s1.multi_concat(s2)
#=> aaaa 
#=> a    bbb
#=> aaaa bbbb

如上所示,我希望它们底部对齐。我试过这个:

class String
  def multi_concat(s2)
    lines.map(&:chomp).zip(s2.lines.map(&:chomp)).map(&:join).join("\n")
  end
end

但它存在三个问题:

  • 这两个块是顶部对齐的。
  • 块之间没有间距。
  • 短线移动内容:
#=> aaaabbb
#=> abbbb
#=> aaaa

如何“阻止连接”它们?

【问题讨论】:

    标签: ruby string concatenation


    【解决方案1】:

    这是一个强大的多行连接器,支持:

    • 用于连接两个块的任意字符串
    • 顶部、底部和中间对齐
    class String
      def multi_concat(str2,options={})
        options[:pad]   ||= ''
        options[:align] ||= :top
    
        chomped1, chomped2 = [self,str2].map{ |s| s.lines.map(&:chomp) }
        template = "%-#{chomped1.map(&:length).max}s#{options[:pad]}%s"
        delta = chomped2.length - chomped1.length
        unless delta==0
          shorter = delta>0 ? chomped1 : chomped2
          delta = delta.abs
          padding = ['']*delta
          case options[:align]
          when :top    then shorter.concat(padding)
          when :bottom then shorter.unshift(*padding)
          when :middle 
            s1,s2 = *padding.each_cons((delta/2.0).ceil)
            shorter.unshift(*s2)
            shorter.concat(s1)
          end
        end
        chomped1.zip(chomped2).map{ |a| template % a }.join("\n")
      end
    end
    

    在行动:

    a = "aaa\naaaa"
    b = "bbbb\n\n\nbb"
    puts a.multi_concat( b )
    #=> aaa bbbb
    #=> aaaa
    #=>     
    #=>     bb
    
    puts a.multi_concat( b, pad:' -> ' )
    #=> aaa  -> bbbb
    #=> aaaa -> 
    #=>      -> 
    #=>      -> bb
    
    puts a.multi_concat( b, pad:' ', align: :bottom )
    #=>      bbbb
    #=>      
    #=> aaa  
    #=> aaaa bb
    
    puts a.multi_concat( b, pad:' ', align: :middle )
    #=>      bbbb
    #=> aaa  
    #=> aaaa 
    #=>      bb
    
    puts b.multi_concat( a, pad:' ' )
    #=> bbbb aaa
    #=>      aaaa
    #=>      
    #=> bb   
    

    【讨论】:

      【解决方案2】:

      我可以发誓这个问题是几周前在这里提出并回答的,但找不到。

      您可以使用 Ruby 的 printf 样式格式:

      #!/usr/bin/env ruby
      
      def format(s1, s2)
        lines1 = s1.split("\n")
        lines2 = s2.split("\n")
        max_s1 = lines1.map { |s| s.length }.max
        format_string = "%-#{max_s1 + 2}s%s"
        lines1.zip(lines2).each do |s1, s2|
          puts format_string % [s1, s2]
        end
      end
      
      
      s1 = "aaaa
      a
      aaaa"
      
      s2 = "bbb
      bbbb"
      
      format(s1, s2)
      

      输出:

      aaaa  bbb
      a     bbbb
      aaaa
      

      【讨论】:

      • 不错。我喜欢使用 sprintf 进行填充 (+ 2),但请注意,此答案不能解决底部对齐要求。
      【解决方案3】:

      我实现了“顶部”和“底部”对齐,但没有实现“中间”对齐,尽管我不认为添加它会很困难。

      def multi_concat_top(s1,s2,sep=' ')
        multi_concat(s1.split("\n"), s2.split("\n"), sep).join("\n")
      end
      
      def multi_concat_bottom(s1,s2,sep=' ')
        multi_concat(s1.split("\n").reverse, s2.split("\n").reverse, sep).
          reverse.join("\n")
      end
      
      def multi_concat(a1,a2,sep)
        mx1 = a1.max_by(&:size).size
        [a1.size, a2.size].max.times.map { |i|
          "%s%s%s" % [a1.fetch(i,'').ljust(mx1), sep, a2.fetch(i,'')] }
      end
      

      s1 = "aaaa\na\naaaa"
      s2 = "bbb\nbbbb"
      
      puts s1
      # aaaa
      # a
      # aaaa
      
      puts s2
      # bbb
      # bbbb
      
      puts multi_concat_top(s1,s2,' -> ')
      # aaaa -> bbb
      # a    -> bbbb
      # aaaa -> 
      
      puts multi_concat_bottom(s1,s2,' -> ')
      # aaaa -> 
      # a    -> bbb
      # aaaa -> bbbb
      

      phrogs(“中间”除外)执行的测试如下。

      s1 = "aaa\naaaa"
      s2 = "bbbb\n\n\nbb"
      
      puts s1
      # aaa
      # aaaa
      puts s2
      # bbbb
      #
      #
      # bb
      
      puts a.multi_concat_top(s1,s2)
      # aaa  bbbb
      # aaaa 
      #     
      #      bb
      
      puts a.multi_concat_top(s1,s2,' -> ' )
      # aaa  -> bbbb
      # aaaa -> 
      #      -> 
      #      -> bb
      
      puts a.multi_concat_bottom(s1,s2)
      #      bbbb
      #      
      # aaa  
      # aaaa bb
      
      puts multi_concat_top(b,a)
      # bbbb aaa
      #      aaaa
      #      
      # bb   
      
      猜你喜欢
      • 2017-07-22
      • 2021-07-08
      • 1970-01-01
      • 2014-09-08
      • 1970-01-01
      • 1970-01-01
      • 2015-06-17
      • 2015-09-18
      • 1970-01-01
      相关资源
      最近更新 更多