iPad上的MonoTouch:如何使文本搜索更快
本文关键字:文本 搜索 何使 上的 MonoTouch iPad | 更新日期: 2023-09-27 18:17:10
我需要在一个相对较大的列表(大约37K行,每行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
是完美(即相同)匹配您现有的代码(它没有做任何文化特定的比较)。
一般来说,我发现包含操作不适合搜索,所以我建议你看看WWDC 2010页面上的Mastering Core Data Session(需要登录)视频(大约10分钟)。苹果知道"contains"在移动设备上对SQLite来说很糟糕,你可以像苹果一样在他们发布的SQLite版本上"破解"FTS。
基本上,它们通过创建一个表来进行前缀匹配:
[[ pk_id || input || normalized_input ]]
其中input和normalized_input 都显式索引。然后,它们对规范化值进行前缀匹配。例如,如果用户正在搜索"依偎",到目前为止他们已经输入了"snu",那么前缀匹配查询将看起来像:
normalized_input >= 'snu' and normalized_input < 'snt'
不确定这是否翻译给你的用例,但我认为这是值得一提的。希望这对你有帮助!
您需要使用trie。见http://en.wikipedia.org/wiki/Trie