Split large string in n-size chunks in JavaScript

Split large string in n-size chunks in JavaScript

I would like to split a very large string (let’s say, 10,000 characters) into N-size chunks.
What would be the best way in terms of performance to do this?
For instance:
“1234567890” split by 2 would become [“12”, “34”, “56”, “78”, “90”].
Would something like this be possible using String.prototype.match and if so, would that be the best way to do it in terms of performance?

Solutions/Answers:

Solution 1:

You can do something like this:

"1234567890".match(/.{1,2}/g);
// Results in:
["12", "34", "56", "78", "90"]

The method will still work with strings whose size is not an exact multiple of the chunk-size:

"123456789".match(/.{1,2}/g);
// Results in:
["12", "34", "56", "78", "9"]

In general, for any string out of which you want to extract at-most n-sized substrings, you would do:

str.match(/.{1,n}/g); // Replace n with the size of the substring

If your string can contain newlines or carriage returns, you would do:

str.match(/(.|[\r\n]){1,n}/g); // Replace n with the size of the substring

As far as performance, I tried this out with approximately 10k characters and it took a little over a second on Chrome. YMMV.

Related:  How to check/uncheck radio button on click?

This can also be used in a reusable function:

function chunkString(str, length) {
  return str.match(new RegExp('.{1,' + length + '}', 'g'));
}

Solution 2:

Bottom line:

  • match is very inefficient, slice is better, on Firefox substr/substring is better still
  • match is even more inefficient for short strings (even with cached regex – probably due to regex parsing setup time)
  • match is even more inefficient for large chunk size (probably due to inability to “jump”)
  • for longer strings with very small chunk size, match outperforms slice on older IE but still loses on all other systems
  • jsperf rocks

Solution 3:

I created several faster variants which you can see on jsPerf. My favorite one is this:

function chunkSubstr(str, size) {
  const numChunks = Math.ceil(str.length / size)
  const chunks = new Array(numChunks)

  for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
    chunks[i] = str.substr(o, size)
  }

  return chunks
}

Solution 4:

This is the fastest, most performant solution:

function chunkString(str, len) {
  var _size = Math.ceil(str.length/len),
      _ret  = new Array(_size),
      _offset
  ;

  for (var _i=0; _i<_size; _i++) {
    _offset = _i * len;
    _ret[_i] = str.substring(_offset, _offset + len);
  }

  return _ret;
}

Compare it to the others; I win 🙂

Related:  Getting requirejs to work with Jasmine

Solution 5:

Surprise! You can use split to split.

var parts = "1234567890 ".split(/(.{2})/).filter(O=>O)

Results in [ '12', '34', '56', '78', '90', ' ' ]

Solution 6:

var str = "123456789";
var chunks = [];
var chunkSize = 2;

while (str) {
    if (str.length < chunkSize) {
        chunks.push(str);
        break;
    }
    else {
        chunks.push(str.substr(0, chunkSize));
        str = str.substr(chunkSize);
    }
}

alert(chunks); // chunks == 12,34,56,78,9