Home > Mobile >  split the string with maximum and minimum length
split the string with maximum and minimum length

Time:10-10

I want to split a string by 3 but with minimum length of 2.

This is I I got so far.

def split_string(s)
  if(s.length % 3 == 1)
    s.slice(0, s.length-4).scan(/.{3}/).join(' ')   ' '   s[s.length-4, s.length].scan(/.{2}/).join(' ')
  else
    s.scan(/.{1,3}/).join(' ')
  end
end

puts split_string("abcdefgh") 
#  abc def gh
puts split_string("abcdefghij") 
#  abc def gh ij

It actually works but I believe there must be more elegant solution than this

CodePudding user response:

You could use Enumerable#each_slice and then correct the result if the last string formed has only a single character.

def doit(str)
  case str.size
  when 0
    []
  when 1
    nil
  else
    str.each_char.each_slice(3).to_a.tap do |arr|
      arr[-1].unshift(arr[-2].pop) if arr[-1].size == 1
    end.map(&:join)
  end
end
test = %w| abcdef abcde abcd abc ab a | << ''
  #=> ["abcdef", "abcde", "abcd", "abc", "ab", "a", ""]
test.each { |s| puts "'%s' -> %s" % [s, doit(s)] }
'abcdef' -> ["abc", "def"]
'abcde' -> ["abc", "de"]
'abcd' -> ["ab", "cd"]
'abc' -> ["abc"]
'ab' -> ["ab"]
'a' -> 
'' -> []

Note that doit('a') #=> nil.


Another way would be to use recursion.

def doit(str)
  case str.size
  when 0
    []
  when 1
    nil
  else
    recurse(str)
  end
end
def recurse(str)
  case str.size
  when 2,3
    [str]
  when 4
    [str[0,2], str[2,2]]
  else
    [str[0,3]]   recurse(str[3..-1])
  end
end        
       

test.each { |s| puts "'%s' -> %s" % [s, doit(s)] } displays the same results as above.

  • Related