使用正则表达式将字符串转换为字典(希望进行优化)

Sim*_*onW 3 .net c# regex optimization dictionary

我在"$0Option one$1$Option two$2$Option three"要转换成字典的格式(等)上有字符串,每个数字对应一个选项。我目前对此问题有一个可行的解决方案,但是由于要为我要导入的每个条目(数千个)调用此方法,因此我希望它尽可能地优化。

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;
}
Run Code Online (Sandbox Code Playgroud)

Ala*_*ore 6

在您的代码中引起我注意的第一件事是,它对输入字符串进行了三次处理:两次使用Split(),一次使用Replace()。该Matches()方法比Split()这项工作要好得多。有了它,您可以一次性提取所需的所有内容。它也使代码更容易阅读。

我注意到的第二件事是所有这些循环和中间对象。您已经在使用LINQ;真正使用它,您就可以消除所有这些混乱情况提高性能。看看这个:

public static Dictionary<int, string> GetSelectValuesDictionary(string inputString)
{
  return Regex.Matches(inputString, @"(?<key>[0-9]+)\$*(?<value>[^$]+)")
    .Cast<Match>()
    .ToDictionary(
        m => int.Parse(m.Groups["key"].Value),
        m => m.Groups["value"].Value);
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • Cast<Match>()之所以有必要是因为MatchCollection只有广告本身会是一个广告IEnumerable,而我们需要它是一个广告IEnumerable<Match>
  • [0-9]不是\d偶然地使用您的值可能包含非拉丁书写系统中的数字;在.NET中,\d将它们全部匹配。
  • 静态Regex方法(例如Matches()自动缓存Regex对象),但是如果要调用此方法很多(尤其是如果您还要使用很多其他正则表达式),则无论如何都可能要创建静态Regex对象。如果性能确实很关键,则可以在使用时指定Compiled选项。
  • 和您一样,我的代码也没有尝试处理格式错误的输入。特别是,如果数字太大,我的将抛出异常,而您的数字只是将其转换为零。这可能与您的实际代码无关,但是我不得不表达我的不安,因为看到您在TryParse()不检查返回值的情况下打电话。:/
  • 您也不能确保密钥是唯一的。像@Gabe一样,我使用数字值作为键来翻转它,因为它们恰好是唯一的,而字符串值不是。我相信您的真实数据也不是问题。;)