有没有一种“更好”或“更高效”的方法来遍历字典?

4
我正在遍历一个字符串列表,以查看该字符串是否包含在字典的值中,然后尝试从该值中删除该字符串。
目前我是这样做的:
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, "");
            }
        }
    }
}

对我来说,这似乎有点冗长。有没有更好的方法来做到这一点?

我的问题为什么被投票贬低了? - 97ldave
如果字典很大,那么这种方法效率相当低下;请记住,字典的设计是为了快速查找与给定键相关联的值,而不是快速查找给定值!如果您需要经常执行此操作,则应该有两个字典;一个常规的“正向”字典,然后是一个“反向”字典,将值映射回一系列相关键。像这样保持两个字典同步会在每个操作上使用更多的空间和时间,但您的操作变得更便宜。 - Eric Lippert
4个回答

5

只需遍历基础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,是因为我不确定你是否知道它。看起来它可能适用于你的代码。


2
由于您已经拥有了 KVP,只需使用 kvp.Value 而不是每次运行时从字典中检索。 - Joe Enos
1
你不能直接给 kvp.Value 赋值。 - Blorgbeard
1
你需要稍微作弊一下,比如:foreach (var kvp in formValues.ToArray()) 这样你就不会在迭代过程中修改被迭代的集合。 - Joe Enos
1
@JoeEnos 这不仅是有点作弊,而且可能会完全破坏“优化”的整个过程。但是,请查看编辑后的帖子,以获取更多优化潜力。 - sehe
1
@sehe,我喜欢使用正则表达式的想法。它看起来比我之前做的更整洁、更好。我会试一试。 - 97ldave
显示剩余3条评论

1
我可能会这样做:

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 ;
}

0
从性能方面考虑,您可以考虑使用某种二叉搜索树,例如三叉搜索树。

0
创建一个自动机,其中每个状态更改都是特定字符,这样如果您想要查找某些内容,只需遵循自动机树并到达所搜索的终端点即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接