【发布时间】:2013-07-14 00:13:29
【问题描述】:
我有一本很大的字典,里面的内容是这样的:
(字典中不包含标题)
(code) (names)
------------------------------
910235487 Diabetes, tumors, sugar sick, .....
我的字典中有超过 150K 行这种对。
用户输入的是关键词(诊断名称),我无法按键搜索字典。
代码如下:
var relevantIDs = this.dic.Where(ele => ele.Value.Contains(keyword)).Select(n => Convert.ToUInt64(n.Key));
字典是Dictionary<string, string>,我必须使用字符串作为键的数据类型,因为代码有时可以包含字符。名称列包含相关诊断名称的列表。所以我也不能改变这个数据类型。
我认为问题出在对的每个值上,我执行了Contains 操作,这会减慢 who 进程,但我找不到替代方法...
这是我为了找到匹配的代码所做的。
但是这段代码的性能很糟糕(完成这一行代码大约需要 5 分钟)。
有人可以帮忙吗?
更新和最简单的解决方案:
我终于找到了为什么搜索这么慢的季节,并通过这样做解决了:
var relevantStringIDs = this.dic.Where(ele => ele.Value.Contains(keyword)).Tolist();
var relevantUlongIDs = relevantStringIDs.Select(n => Convert.ToUInt64(n.Key)).Tolist();
这么慢的原因是this.dic.Where(ele => ele.Value.Contains(keyword)),每次执行第二部分查询时都会执行(这是IEnumberable<T>的特点,我忘记了它的术语(可能延迟执行))。所以我使用ToList()将延迟查询转换为内存中的具体列表,以便在将字符串转换为ulongs时可以重复使用结果,而不是每次转换都再次执行查询。
如果您在此说明中发现错误,请纠正我。
顺便说一句,虽然这可能不是最好的解决方案,但更改后的代码的性能还是令人满意的。代码的第一条语句只花费了 169 毫秒,这对我来说已经足够快了。
【问题讨论】:
-
大家好,请不要在不告诉我原因的情况下否决我的问题。我检查了其他类似的问题,但没有一个真正解决了我的问题。
-
如果您的代码可以包含字符,那么您将很难将它们全部转换为 Int64...
-
术语是“deferred execution”。但是,在
Where和Select之间发出额外的ToList在这种情况下不太可能有助于提高性能。如果您多次迭代最终结果(我假设您是这样),那么您主要受益于 finalToList。尝试将您的代码从dic.Where(...).ToList().Select(...).ToList()更改为dic.Where(...).Select(...).ToList()- 您将观察到性能几乎没有变化。
标签: c# performance algorithm search dictionary