I have string on the format "$0Option one$1$Option two$2$Option three" (etc) that I want to convert into a dictionary where each number corresponds to an option. I currently have a working solution for this problem, but since this method is called for every entry I’m importing (few thousand) I want it to be as optimized as possible.
public Dictionary<string, int> GetSelValsDictBySelValsString(string selectableValuesString)
{
// Get all numbers in the string.
var correspondingNumbersArray = Regex.Split(selectableValuesString, @"[^\d]+").Where(x => (!String.IsNullOrWhiteSpace(x))).ToArray();
List<int> correspondingNumbers = new List<int>();
int number;
foreach (string s in correspondingNumbersArray)
{
Int32.TryParse(s, out number);
correspondingNumbers.Add(number);
}
selectableValuesString = selectableValuesString.Replace("$", "");
var selectableStringValuesArray = Regex.Split(selectableValuesString, @"[\d]+").Where(x => (!String.IsNullOrWhiteSpace(x))).ToArray();
var selectableValues = new Dictionary<string, int>();
for (int i = 0; i < selectableStringValuesArray.Count(); i++)
{
selectableValues.Add(selectableStringValuesArray.ElementAt(i), correspondingNumbers.ElementAt(i));
}
return selectableValues;
}
The first thing that caught my attention in your code is that it processes the input string three times: twice with
Split()and once withReplace(). TheMatches()method is a much better tool thanSplit()for this job. With it, you can extract everything you need in a single pass. It makes the code a lot easier to read, too.The second thing I noticed was all those loops and intermediate objects. You’re using LINQ already; really use it, and you can eliminate all of that clutter and improve performance. Check it out:
notes:
Cast<Match>()is necessary becauseMatchCollectiononly advertises itself as anIEnumerable, and we need it to be anIEnumerable<Match>.[0-9]instead of\don the off chance that your values might contain digits from non-Latin writing systems; in .NET,\dmatches them all.Matches()automatically cache the Regex objects, but if this method is going to be called a lot (especially if you’re using a lot of other regexes, too), you might want to create a static Regex object anyway. If performance is really critical, you can specify theCompiledoption while you’re at it.TryParse()without checking the return value. :/