情况如下:
我有一个网页,我已经把它作为一个字符串。
我在MSSQL数据库中有几个字段。例如,汽车模型,它有一个ID和一个名称,如Mustang或Civic。它预装了大多数车型。
我想找到我的模型表中任何行的匹配项。所以,如果我在我的模型表中有Civic,Mustang和E350,我想找到我已经刮过的页面中任何三个中的任何一个。
在C#中执行此操作的有效方法是什么?我正在使用LINQ to SQL与db进行交互。
创建所有模型的字典,标记页面和迭代标记是否有意义?或者我应该迭代标记并使用WHERE子句并询问数据库是否匹配?
//Dictionary dic contains all models from the DB, with the name being the key and the id being the value...
foreach(string pageToken in pageTokens)
{
if(dic.ContainsKey(pageToken))
{
//Do what I need to do
}
}
这两种方法对我来说都很糟糕。关于我应该做什么的任何建议?设想交叉点的东西我觉得可能会很好吗?
这两种方法都没有解决当模型名称多于一个单词时发生的情况。如“F150 Extended Cab”。对此的想法?
答案 0 :(得分:5)
在较大的文本中搜索多个字符串是一个众所周知的问题,并且已经进行了大量研究以使其快速进行。对此最常用和最有效的两种方法是Aho-Corasick Algorithm(我推荐这个)和Rabin-Karp Algorithm。他们使用了一些预处理,但是数量级不那么复杂。比naieve方法更快(naieve方法是最坏情况O(m * n ^ 2 * p),其中m是长串[你刮的网页]的长度,n是针的平均长度,p是针数)。 Aho-Corsaik是线性的。 A C# implementation of it can be found at CodeProject for free.
编辑:哎呀,我错了Aho-Corasick的复杂性 - 它的数字和数字是线性的。输入字符串的长度+正在分析的字符串的大小[已删除的文本]加上匹配的数量。但它仍然是线性的,线性比立方更好: - )。
答案 1 :(得分:3)
我的第一种方法是超级简单:
foreach(string carModel in listOfCarModelsFromDatabase) {
if(pageText.Contains(carModel) {
// do something
}
}
如果上述速度不够快,我只会开始担心如何加快速度。汽车模型列表不可能是那么大(<10000?)而且它只是一页文本。
答案 2 :(得分:0)
您应该使用正则表达式,而不是基于空格进行标记。
使用Regex你可以使用空格并且很好,我相信它会比标记化和循环遍历可能的值列表更快。
虽然我不确定如何构建该正则表达式。
最简单的说,您可以使用
等每个模型构建一个正则表达式(Model 1|Model 2|Model 3)
但我确信在正则表达式中有更有效的方法可以做到这一点。
答案 3 :(得分:0)
对于一个非常简单的子串匹配解决方案(应该运行得相当好),你可以使用这样的参数化SQL查询:
select ModelID, ModelName
from Model
where ? like '%' + ModelName + '%'
其中?
是一个被整个网页文本替换的参数。