文字列の粗いカット

1335 ワード

class String
  def chunk(size = 10, sclice_on = /\s+/)
    out = []
    slices_estimate = self.size.divmod(size)
    slice_count = (slices_estimate[1] > 0 ? slices_estimate[0] + 1 : slices_estimate[0])
    slice_guess = self.size / slice_count
    previous_slice_location = 0
    (1..slice_count - 1).each do|i|
      slice_location = self.nearest(slice_guess * i, sclice_on)
      out << self.slice(previous_slice_location..slice_location)
      previous_slice_location = slice_location + 1
    end
    out << self.slice(previous_slice_location..self.size)
    out
  end

  def nearest(slice_start, slice_on)
    left_location  = (self.slice(0..slice_start).rindex(slice_on)).to_i
    right_location = (self.slice((slice_start + 1)..self.size).index(slice_on)).to_i + slice_start
    ((slice_start - left_location) < (right_location - slice_start) ? left_location : right_location)
  end
end

 
具体例:
 
str = "abcdefghijklmnopqrstuvwxyz"
p str.chunk      # => ["abcdefghi", "jklmnopq", "rstuvwxyz"]
p str.chunk(20)  # => ["abcdefghijklmn", "opqrstuvwxyz"]