Inspired by this question: Split a string into chunks of the same length
The code is designed to work on text elements rather than chars to avoid unicode problems.
public static class StringExtensions
{
public static IEnumerable<string> Partition(this string value, int chunkSize)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
if (chunkSize < 1)
{
throw new ArgumentOutOfRangeException(nameof(chunkSize));
}
var sb = new StringBuilder(chunkSize);
var enumerator = StringInfo.GetTextElementEnumerator(value);
while (enumerator.MoveNext())
{
sb.Append(enumerator.GetTextElement());
for (var i = 0; i < chunkSize - 1; i++)
{
if (!enumerator.MoveNext())
{
break;
}
sb.Append(enumerator.GetTextElement());
}
yield return sb.ToString();
sb.Length = 0;
}
}
}
And a couple of unit tests
[TestMethod]
public void Partition_SplittingAnAsciiString_ShouldSplitTheStringIntoTheRequiredChunkSize()
{
string input = "123456";
string[] expected = { "123", "456" };
string[] actual = input.Partition(3).ToArray();
CollectionAssert.AreEqual(expected, actual);
}
[TestMethod]
public void Partition_SplittingAPartiallyDecomposedString_ShouldSplitTheStringIntoTheRequiredChunkSize()
{
string input = "éée\u0301";
string[] expected = { "é", "é", "e\u0301" };
string[] actual = input.Partition(1).ToArray();
CollectionAssert.AreEqual(expected, actual);
}
I usually use Machine Specifications for unit tests so any tips on writing MSTest unit tests would be great especially naming conventions!
The method feels slightly too long to me but I couldn't see a nice way of splitting it up.