我需要在相对较大的列表(大约 37,000 行,每行 50 到 100 个字符)中根据用户输入进行文本搜索。输入每个字符后完成搜索,结果显示在 UITableView
中。这是我当前的代码:
if (input.Any(x => Char.IsUpper(x)))
return _list.Where(x => x.Desc.Contains(input));
else
return _list.Where(x => x.Desc.ToLower().Contains(input));
它在 MacBook 运行模拟器上运行良好,但在 iPad 上运行速度太慢。
我观察到的一件有趣的事情是,随着输入的增加,它需要的时间越来越长。例如,说“examin”作为输入。输入e后大约需要1秒,输入x后需要2秒,输入a后需要5秒,但输入m后需要28秒,依此类推。为什么?
我希望有一个简单的方法来改进它。
最佳答案
始终注意在时间敏感代码中避免内存分配。
例如我们经常产生的代码经常在没有意识到的情况下分配string
,例如
x => x.Desc.ToLower().Contains(input)
这将分配一个字符串以从 ToLower
返回。根据您的描述,这会发生多次。您可以使用以下方法轻松避免这种情况:
x = x.Desc.IndexOf ("s", StringComparison.OrdinalIgnoreCase) != -1
注意:只需选择符合您需要的 StringComparison.*IgnoreCase
。
LINQ 也很好,但它在许多情况下隐藏了分配 - 也许不是您的情况,但测量是加快速度的关键。在这种情况下,使用另一种算法(如另一个答案中建议的那样)可以为您提供更好的结果(但请记住分配;-)
更新:
Mono 的 Contains(string)
将在几次检查后调用以下内容:
CultureInfo.CurrentCulture.CompareInfo.IndexOf (this, value, 0, length, CompareOptions.Ordinal);
根据您的 ToLower
要求,使用 StringComparison.OrdinalIgnoreCase
是您现有代码的完美(即相同)匹配(它确实不做任何特定于文化的比较)。
关于c# - iPad 上的 MonoTouch : How to make text search faster?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8441484/