What is the best way to chop a string into chunks of a given length in Ruby?

MiniQuark picture MiniQuark · Apr 16, 2009 · Viewed 36.1k times · Source

I have been looking for an elegant and efficient way to chunk a string into substrings of a given length in Ruby.

So far, the best I could come up with is this:

def chunk(string, size)
  (0..(string.length-1)/size).map{|i|string[i*size,size]}
end

>> chunk("abcdef",3)
=> ["abc", "def"]
>> chunk("abcde",3)
=> ["abc", "de"]
>> chunk("abc",3)
=> ["abc"]
>> chunk("ab",3)
=> ["ab"]
>> chunk("",3)
=> []

You might want chunk("", n) to return [""] instead of []. If so, just add this as the first line of the method:

return [""] if string.empty?

Would you recommend any better solution?

Edit

Thanks to Jeremy Ruten for this elegant and efficient solution: [edit: NOT efficient!]

def chunk(string, size)
    string.scan(/.{1,#{size}}/)
end

Edit

The string.scan solution takes about 60 seconds to chop 512k into 1k chunks 10000 times, compared with the original slice-based solution which only takes 2.4 seconds.

Answer

Paige Ruten picture Paige Ruten · Apr 16, 2009

Use String#scan:

>> 'abcdefghijklmnopqrstuvwxyz'.scan(/.{4}/)
=> ["abcd", "efgh", "ijkl", "mnop", "qrst", "uvwx"]
>> 'abcdefghijklmnopqrstuvwxyz'.scan(/.{1,4}/)
=> ["abcd", "efgh", "ijkl", "mnop", "qrst", "uvwx", "yz"]
>> 'abcdefghijklmnopqrstuvwxyz'.scan(/.{1,3}/)
=> ["abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz"]