I am writing a custom string split. It will split on a dot(.) that is not preceded by an odd number of backslashes (\).
«string» -> «IEnemerable<string>»
"hello.world" -> "hello", "world"
"abc\.123" -> "abc\.123"
"aoeui\\.dhtns" -> "aoeui\\","dhtns"
I would like to know if there is a substring that will reuse the original string (for speed), or is there an existing split that can do this fast?
This is what I have but is 2—3 times slower than input.Split('.') //where input is a string. (I know it is a (slightly more complex problem, but not that much)
public IEnumerable<string> HandMadeSplit(string input)
{
var Result = new LinkedList<string>();
var word = new StringBuilder();
foreach (var ch in input)
{
if (ch == '.')
{
Result.AddLast(word.ToString());
word.Length = 0;
}
else
{
word.Append(ch);
}
}
Result.AddLast(word.ToString());
return Result;
}
It now uses List instead of LinkedList, and record beginning and end of substring and use string.substring to create the new substrings. This does a lot and is nearly as fast as string.split but I have added my adjustments. (will add code)
The loop that you show is the right approach if you need performance. (Regex wouldn’t be).
Switch to an index-based for-loop. Remember the index of the start of the match. Don’t append individual chars. Instead, remember the range of characters to copy out and do that with a single
Substringcall per item.Also, don’t use a
LinkedList. It is slower than aListfor almost all cases except random-access mutations.You might also switch from
Listto a normal array that you resize withArray.Resize. This results in slightly tedious code (because you have inlined a part of theListclass into your method) but it cuts out some small overheads.Next, don’t return an
IEnumerablebecause that forces the caller through indirection when accessing its items. Return aListor an array.