Chop a string in Ruby into fixed length string ignoring (not considering/regardless) new line or space characters

前端 未结 5 1023
别那么骄傲
别那么骄傲 2021-01-02 21:19

I have a string containing many new line and spaces. I need to split it into fixed length sub strings. E.g

a = \"This is some\\nText\\nThis is some text\"
<         


        
5条回答
  •  不知归路
    2021-01-02 21:51

    Yet another solution: unpack.

    You need to construct a string for it like a17a17a17a17a8 (the last chunk needs to be shorter if the string is not exactly x times 17 chars long.

    a = "This is some\nText\nThis is some text\nThis is some more text"
    a.unpack(('a17' * (a.length / 17)) + (a.size % 17 == 0 ? "" : "a#{a.length - (a.length / 17) * 17}"))
     => ["This is some\nText", "\nThis is some tex", "t\nThis is some mo", "re text"]
    

    This appears to be by far the fastest one of the suggested, of course if the input string is huge, the unpack string will be huge as well. If that is the case, you will want a buffered reader for that thing, read it in chunks of x * 17 and do something like the above for each chunk.

    require 'benchmark'
    a = "This is some\nText\nThis is some text" * 1000
    n = 100
    
    Benchmark.bm do |x|
      x.report("slice ") { n.times do ; (0..(a.length / 17)).map{|i| a[i * 17,17] } ; end}
      x.report("regex ") { n.times do ; a.scan(/.{1,17}/m) ; end}
      x.report("eachc ") { n.times do ; a.each_char.each_slice(17).map(&:join) ; end }
      x.report("unpack") { n.times do ; a.unpack(('a17' * (a.length / 17)) + (a.size % 17 == 0 ? "" : "a#{a.length - (a.length / 17) * 17}")) ; end }
    end
    

    Results:

    user    system     total      real
    slice   0.120000   0.000000   0.120000 (  0.130709)
    regex   0.190000   0.000000   0.190000 (  0.186407)
    eachc   1.430000   0.000000   1.430000 (  1.427662)
    unpack  0.030000   0.000000   0.030000 (  0.032807)
    

提交回复
热议问题