The Aim
Since I very rarely write code to do things other than business logic anymore I've set myself a challenge:
Split a string into a list of substrings by splitting on a matching string, without using string.Split()
or similar methods of string
(substring, indexof, etc) or LINQ methods (edit or regex /edit).
The method must also accept a parameter stating whether the return list is allowed to contain empty strings (only excludes string.Empty
, not whitespace).
The Code
private static IList<string> SplitString(string toSplit, string splitOn, bool allowEmptyResults = true)
{
int cursorPosition = 0;
int innerCursor = 0;
var strings = new List<string>();
while (cursorPosition < toSplit.Length)
{
bool match = false;
for (int i = 0; i < splitOn.Length ; i++)
{
match = toSplit[innerCursor] == splitOn[i];
if ((i < splitOn.Length - 1 && innerCursor == toSplit.Length - 1) || !match)
{
match = false;
break;
}
innerCursor++;
}
if (match)
{
var result = StringFromCursor(toSplit, cursorPosition, innerCursor - splitOn.Length);
if (result != string.Empty || allowEmptyResults)
{
strings.Add(result);
}
cursorPosition = innerCursor;
}
else
{
if (innerCursor < toSplit.Length - 1)
{
innerCursor++;
}
else
{
var result = StringFromCursor(toSplit, cursorPosition, toSplit.Length);
if (result != string.Empty || allowEmptyResults)
{
strings.Add(result);
}
break;
}
}
}
return strings;
}
private static string StringFromCursor(string toSplit, int cursorPosition, int matchStart)
{
string result = string.Empty;
for (int i = cursorPosition; i < matchStart; i++)
{
result += toSplit[i].ToString();
}
return result;
}
The Problem
This seems hopelessly complicated and prone to "off by 1" errors, I'm more interested in the cleaner logic for accomplishing this task rather than making it cleaner by refactoring into smaller methods.
Also I'm not too concerned about style (inconsistent use of var
for example).
The code spends a large number of characters trying to deal with tricky behaviour at the end of a string but seems to work for the following test cases:
var result = SplitString("thetgonceupon the time there was a thing there", "the");
var result = SplitString("thetgonceupon the time there was a thing thereth", "the");
var result = SplitString("thetgonceupon the time there was a thing therethe", "the");
String.Split
, are you also looking to avoid LINQ methods? \$\endgroup\$Regex.Split(toSplit, splitOn);
however you could build in whether to accept whitespaces or not. I only asked because it wasn't explicitly stated as a constraint. \$\endgroup\$