From: Rob Biedenharn Date: 2007-02-03T00:55:42+09:00 Subject: Re: halving a string On Feb 1, 2007, at 11:10 PM, Chris Shea wrote: > I have a vacuum fluorescent display in my office, and I've been > messing around with it. Now that I've figured out how to communicate > with the serial connection it's time for some fun. Its shortcoming is > its 2 lines of 20 chars. So I naturally wrote a fortune cookie program > for it. > > I want to make adding new fortunes easy (and without having to figure > out myself where to force a line break), so I basically need to split > a string (approximately) in half at a word boundary. This is what I > have: > > class String > def halve > first_half = '' > second_half = self > until first_half.length >= length / 2 > match = / /.match(second_half) > first_half << match.pre_match << ' ' > second_half = match.post_match > end > [first_half.strip, second_half] > end > end > > I have a feeling there's a one-line regexp that can do this. Am I > right? If not, is there a better way? Good solutions already, but I had to chime in with one less clever and without regexps. I also didn't like "halve" as a name so I used "cleave". Enjoy! class String def cleave middle = self.length/2 early = self.rindex(' ', middle) late = self.index(' ', middle) if self[middle,1] == ' ' [ self[0...middle], self[middle+1..-1] ] elsif early.nil? && late.nil? [ self.dup, '' ] elsif early.nil? [ self[0...late], self[late+1..-1] ] elsif late.nil? [ self[0...early], self[early+1..-1] ] else middle = middle - early < late - middle ? early : late [ self[0...middle], self[middle+1..-1] ] end end end if __FILE__ == $0 require 'test/unit' class StringCleaveTest < Test::Unit::TestCase def test_nospaces assert_equal [ 'whole', '' ], 'whole'.cleave assert_equal [ 'Supercalifragilisticexpialidocious', '' ], 'Supercalifragilisticexpialidocious'.cleave end def test_exact_middle assert_equal [ 'fancy', 'split' ], 'fancy split'.cleave assert_equal [ 'All good Rubyists', 'know how to party' ], 'All good Rubyists know how to party'.cleave end def test_closer_to_start assert_equal [ 'short', 'splitter' ], 'short splitter'.cleave assert_equal [ 'Four score and', 'seven years ago...' ], 'Four score and seven years ago...'.cleave assert_equal [ 'abc def', 'ghijklm nop' ] , 'abc def ghijklm nop'.cleave end def test_closer_to_end assert_equal [ 'extended', 'split' ], 'extended split'.cleave assert_equal [ 'abc defghi', 'jklm nop' ] , 'abc defghi jklm nop'.cleave end end end Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com