【问题标题】:Is there a "better" or a "better performance" way of looping though a dictionary是否有一种“更好”或“更好的性能”循环遍历字典的方式
【发布时间】:2013-10-31 23:33:50
【问题描述】:

我正在遍历字符串列表以查看该字符串是否包含在字典的值中,然后尝试从值中删除该字符串。

目前我是这样做的:

Dictionary<String, String> formValues = new Dictionary<String, String>();
formValues["key1"] = "the something at";
formValues["key2"] = "the something on";
formValues["key3"] = "the something is";

string prepositionList = "at,as,if,of,the,to,a,an,it,is,by,its";
List<string> prepositionListValues = new List<string>(prepositionList.Split(','));

foreach (string preposition in prepositionListValues)
{
    List<string> keys = new List<string>(formValues.Keys);
    foreach (string key in keys)
    {
        if (formValues[key] != null)
        {
            if (formValues[key].Contains(preposition))
            {
                formValues[key] = formValues[key].Replace(preposition, "");
            }
        }
    }
}

对我来说,这似乎有点啰嗦。有没有“更好”的方式来做到这一点?

【问题讨论】:

  • 为什么我的问题被否决了?
  • 如果字典很大,那么这是非常低效的;请记住,字典旨在快速查找与给定键关联的值,而不是快速查找给定值!如果这是一个你必须做很多的操作,那么你应该有两个字典;一个常规的“正向”字典,然后是一个从值映射回关联键序列的“反向”字典。像这样保持两个字典同步会在每次操作上占用更多空间和时间,但您的操作会变得更便宜。

标签: c# dictionary foreach


【解决方案1】:

只需迭代底层 IEnumerable 的 KeyvaluePair 条目:

foreach (var kvp in formValues)
{
    if (kvp.Value != null && kvp.Value.Contains(preposition))
    {
        formValue[kvp.Key] = kvp.Value.Replace(preposition, "");
    }
}

警告:在枚举集合的同时修改集合并不是一个好的计划。在这种情况下,我想没问题。

无论如何,

您真正想要在这里实现的是多次替换。

为什么不使用正则表达式:

private static readonly myRegex = new Regex("at|as|if|of|the|to|a|an|it|is|by|its", 
                RegexOptions.Compiled | RegexOptions.IgnoreCase);

// ..

someValue = myRegex.Replace(someValue, "");

我展示了IgnoreCase,以防你不知道。看起来它可能适用于您的代码。

【讨论】:

  • 既然你已经获得了 KVP,只需执行kvp.Value 而不是每次运行都从字典中检索
  • 虽然你不能分配给kvp.Value
  • 您必须作弊,例如:foreach (var kvp in formValues.ToArray()),这样您就不会在迭代时修改迭代集合。
  • @JoeEnos 这不仅仅是作弊。这可能会破坏整个“优化”。但是,请参阅编辑后的帖子了解更多优化潜力
  • @sehe 我喜欢使用正则表达式的想法。它看起来比我正在做的更整洁和更好。我试试看。
【解决方案2】:

我可能会这样做:

Dictionary<string,string> Clean( Dictionary<string,string> dictionary , params string[] words )
{
  string pattern = @"\b(" + string.Join( "|" , words.Select( Regex.Escape ) ) + @")\b" ;
  Regex rx = new Regex(pattern,RegexOptions.IgnoreCase) ;

  foreach ( string key in dictionary.Keys )
  {
    dictionary[key] = rx.Replace(dictionary[key],"") ;
  }

  return dictionary ;
}

【讨论】:

    【解决方案3】:

    就性能而言,您可能会考虑使用某种二叉搜索树,例如三元搜索树。

    【讨论】:

      【解决方案4】:

      创建一个自动机怎么样,因为每次状态变化都是一个特定的角色。 然后,如果你想找到一些东西,你只需要跟随自动机树并到达搜索到的东西所在的终点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-29
        • 2013-02-12
        • 1970-01-01
        • 2013-04-13
        • 1970-01-01
        • 2020-06-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多