This will give better performance (3 times faster in my test, partitioning into length-two strings) than your original code:
chunk[s_, n_] := FromCharacterCode@Partition[ToCharacterCode[s], n]
The reason is that the first few steps of the computation are done with packed arrays.
It will still be slower than the regex-based approaches (István's and Jens's), on my machine by a factor of 2.
The StringTake
approach is much slower than all the others in my machine.
Benchmarks
Function definitions:
(* original *)
chunk1[s_, n_] := StringJoin[#] & /@ Partition[Characters[s], n]
(* István *)
chunk2[s_, n_] := StringCases[s, Repeated[_, {n}]]
(* Jens *)
chunk3[s_, n_] := StringCases[s, RegularExpression[".{1," <> ToString[n] <> "}"]]
(* TomD *)
chunk4 = StringTake[#, Partition[Range@StringLength@#, #2, #2, 1, {}]] &;
(* mine *)
chunk5[s_, n_] := FromCharacterCode@Partition[ToCharacterCode[s], n]
text = ExampleData[{"Text", "Hamlet"}];
testString = StringJoin[ConstantArray[text, 20]];
StringLength[testString] (* 3438740 *)
Timings:
(* original *)
In[10]:= Timing[chunk1[testString, 2];]
Timing[chunk1[testString, 100];]
Out[10]= {5.968, Null}
Out[11]= {1.703, Null}
(* István - fastest *)
In[12]:= Timing[chunk2[testString, 2];]
Timing[chunk2[testString, 100];]
Out[12]={1.25, Null}
Out[13]={0.11, Null}
(* Jens - fastest *)
In[14]:= Timing[chunk3[testString, 2];]
Timing[chunk3[testString, 100];]
Out[14]= {1.313, Null}
Out[15]= {0.125, Null}
(* TomD *)
In[16]:= Timing[chunk4[testString, 2];]
Timing[chunk4[testString, 100];]
(* More than a few minutes. Didn't wait for it to finish ... *)
(* mine *)
In[18]:= Timing[chunk5[testString, 2];]
Timing[chunk5[testString, 100];]
Out[18]= {2.25, Null}
Out[19]= {0.266, Null}
Conclusion: use regex-based methods. The built-in string patterns also use a regex library internally, I believe, but they are easier to construct programmatically because they are represented as expressions.
StringJoin[#] &
is the same as justStringJoin
. $\endgroup$