【问题标题】:C# Replace a text in string with if the text contains in String listC# 如果文本包含在字符串列表中,则将字符串中的文本替换为
【发布时间】:2016-05-13 05:32:49
【问题描述】:

我正在尝试用 Dictionary Value 替换字符串中的文本,如果它与 Dictionary Key 匹配。 从 Table1 中选择 *,其中 column1 ={Value1} 和 Column2 = {value2}。

mydict.Add({value1},OriginalValue1);
mydict.Add({value2},OriginalValue2);

我可以遍历字典键并替换字符串中的文本,但如果 Dictionary 对象中有超过 100 个项目,这会影响性能。

foreach(string key in mydict.keys)
{
if(Query.Contains(key)
{
 //Replace the string
}

有没有办法在对性能影响最小的情况下实现这一点?

【问题讨论】:

  • 是什么让您认为它会对性能产生足够大的影响? Dictionary 类速度很快。
  • 如果您的字典包含“将 a 更改为 b”和“将 b 更改为 a”,当字典适用于“ab”时,您期望什么?输出“ba”还是“aa”?
  • 实际上使用字典应该没有太大区别,因为 OP 无论如何都会遍历所有键。搜索特定键时,字典速度很快。
  • 为性能而设计被认为是不好的形式。构建,然后根据需要考虑性能。

标签: c# str-replace


【解决方案1】:

首先警告:在您知道自己确实存在性能问题之前,不要为了优化而将事情复杂化。 100 个替代品对我来说听起来没什么大不了的。通常,代码可读性和解决实际问题的时间比节省的 10ns 更有价值。

假设每一纳秒都非常重要,那么您应该衡量您的基线并考虑改进选项:

  • 从内置的简单工具开始,例如String.Replace()。它们在内部通常比您自己可以做的更优化(除非您知道输入或所需行为的一些重要的额外限制)
  • 在替换之前不要做额外的Contains(key),因为无论如何您都需要搜索替换的确切位置。如果您选择处理索引,或者像使用 String.IndexOf(..)) 一样重复使用第一遍。
  • 如果您的密钥具有相似的可识别模式(例如:“Key1”、“Key2”等),那么也许您可以使用已编译的 Regex 替换工具一次性完成所有替换?
  • 输入查询是否已修复? StringBuilder.Append() 可能比搜索和替换快 100 倍。
  • 如果需要迭代所有对,为什么要使用字典?跳过堆中的哈希魔法和额外的对象并循环简单的键值对。并不是说您会感觉到性能上有显着差异..

再一次 - 测量!使用 .net 分析器并测量真正的瓶颈在哪里,并确定最适合您的特定场景的方法。

无论您决定使用什么重要的解决方案,请记住,下一个维护您的代码的人可能知道您住在哪里。

【讨论】:

  • 感谢您回答我的问题。我只是希望我能像你提到的那样得到解决方案。但我仍在学习正则表达式工具//如果您的键具有相似的可识别模式(例如:“Key1”、“Key2”等),那么也许您可以使用 a 一次性完成所有替换编译正则表达式替换工具?//
  • 是的。类似的东西
【解决方案2】:

只是速度和字典性能的一个例子。这是 4 岁 i7-3820 上的一个线程

  • 在 0ms 时间内在字符串“一些 11998948 输入”中找到 1
  • 在 0ms 时间内在字符串“一些 11998948 输入”中找到 4 个
  • 在 1ms 内找到字符串“一些 11998948 输入”中的 8 个
  • 在 1ms 的时间内在字符串“一些 11998948 输入”中找到 9 个
  • 在 1 毫秒内找到字符串“一些 11998948 输入”中的 11 个
  • 在 1ms 的时间内在字符串“一些 11998948 输入”中找到 19 个
  • 在 1ms 的时间内在字符串“一些 11998948 输入”中找到 48 个
  • 在 1ms 的时间内在字符串“一些 11998948 输入”中找到 89 个
  • 在 1ms 的时间内在字符串“一些 11998948 输入”中找到 94 个
  • 在 1ms 的时间内在字符串“一些 11998948 输入”中找到 98 个
  • 在 1ms 的时间内在字符串“一些 11998948 输入”中找到 99 个
  • 在 1ms 时间内在字符串“一些 11998948 输入”中找到 119
  • 在 1ms 时间内在字符串“一些 11998948 输入”中找到 199 个
  • 在 1ms 时间内在字符串“一些 11998948 输入”中找到 894 个
  • 在 2ms 内找到字符串“some 11998948 input”中的 948 个
  • 在 2ms 的时间内在字符串“一些 11998948 输入”中找到 989
  • 在 2ms 的时间内在字符串“一些 11998948 输入”中找到 998 个
  • 在 2ms 的时间内在字符串“一些 11998948 输入”中找到 1199
  • 在 2ms 的时间内在字符串“一些 11998948 输入”中找到 1998
  • 在 3 毫秒的时间内在字符串“一些 11998948 输入”中找到 8948
  • 在 3 毫秒的时间内在字符串“一些 11998948 输入”中找到 9894
  • 在 3 毫秒的时间内在字符串“一些 11998948 输入”中找到 9989
  • 在 4 毫秒内在字符串“一些 11998948 输入”中找到 11998
  • 在 5ms 的时间内在字符串“一些 11998948 输入”中找到 19989
  • 在 21 毫秒的时间内在字符串“一些 11998948 输入”中找到 98948
  • 在 21 毫秒内在字符串“一些 11998948 输入”中找到 99894
  • 在 25 毫秒内在字符串“一些 11998948 输入”中找到 119989
  • 在 42 毫秒的时间内在字符串“一些 11998948 输入”中找到 199894
  • 在 214 毫秒的时间内在字符串“一些 11998948 输入”中找到 998948
  • 在 255 毫秒的时间内在字符串“一些 11998948 输入”中找到 1199894
  • 在 400 毫秒的时间内在字符串“一些 11998948 输入”中找到 1998948
  • 在 2127 毫秒的时间内在字符串“一些 11998948 输入”中找到 11998948

这意味着遍历大约 1200 万个元素大约需要 2 秒。字典不是你的问题。 (但我认为可能是部分匹配)

我用这段代码运行它。

Dictionary<string, string> dic = new Dictionary<string, string>();
for (int i = 0; i < 11998949; i++) //11998949 is max supported range
{
    dic.Add(i.ToString(), i.ToString());
}

Stopwatch sw = new Stopwatch();
sw.Start();
string Query = "some 11998948 input"; 
foreach(var a in dic.Where(a=> Query.Contains(a.Key)))
{
    Console.WriteLine($"Found {a.Key} in string {Query} in time {sw.ElapsedMilliseconds}ms");
}
Console.ReadKey();

【讨论】:

  • 这很有趣。我不知道字典更快。感谢您的详细解释。
  • 好吧 dic 可能比其他多种集合类型慢,但它仍然非常快,并且您可以在键上获得 hashmap 功能,它是一个唯一的对象,而不仅仅是一个索引号。
猜你喜欢
  • 2020-02-03
  • 2020-08-15
  • 2013-03-29
  • 2021-07-04
  • 1970-01-01
  • 2011-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多