c# - 在字符串中查找关键字和关键短语的算法

标签 c# sql sql-server algorithm search

我需要有关如何编写算法以在字符串中查找关键字或关键短语的建议或指导。

字符串包含:

  • 以英语 (GB) 编写的技术信息
  • 单词之间大多用空格隔开
  • 关键字不包含空格,但可以包含连字符、撇号、冒号等。
  • 关键词可以包含空格、逗号或其他标点符号
  • 如果两个或多个关键字一起出现,那么它很可能是一个关键短语,例如“变频驱动”
  • 文本还包含 HTML,但如有必要,可以事先将其删除
  • 非关键字可以是“and”、“the”、“we”、“see”、“look”等词。
  • 关键字不区分大小写,例如“逆变器”和“逆变器”是同一个关键字

算法有如下要求:

  1. 批处理场景中操作,例如每天跑一次或两次
  2. 处理长度从大约 200 到 7000 个字符不等的字符串
  3. 在不到 1 小时内处理 1000 个字符串
  4. 将在功率适中的服务器上执行
  5. 使用以下语言之一编写:C#、VB.NET 或 T-SQL 甚至可能是 F#、Python 或 Lua 等。
  6. 依赖预定义关键字或关键短语列表
  7. 但可以依赖关键字排除列表,例如“和”、“该”、“去”等。
  8. Ideally transferable 到其他语言,例如不依赖特定于语言的功能,例如元编程
  9. 输出关键短语列表(频率降序),然后是关键字列表(频率降序)

如果它能在几秒钟内处理多达 8000 个字符,这样它就可以实时运行,那就更酷了,但我的要求已经够多了!

只是寻求建议和方向:

  • 是否应将其视为两个独立的算法?
  • 有没有我可以遵循的既定算法?
  • 我的要求是否可行?

非常感谢。

附言字符串将从 SQL Server 2008 R2 数据库中检索,因此理想情况下该语言应支持这一点,如果不支持,则它必须能够读取/写入 STDOUT、管道、流或文件等。

最佳答案

所涉及的逻辑使得在 T-SQL 中进行编程变得复杂。选择一种语言,例如 C#。首先尝试制作一个简单的桌面应用程序。之后,如果您发现将所有记录加载到此应用程序太慢,您可以编写一个在 SQL-Server 上执行的 C# 存储过程。根据 SQL-Server 的安全策略,它需要有一个强 key 。


现在到算法。排除词列表通常称为停用词列表。如果您对该搜索词进行一些谷歌搜索,您可能会找到可以开始使用的停用词列表。将这些停用词添加到 HashSet<T> (我将在这里使用 C#)

// Assuming that each line contains one stop word.
HashSet<string> stopWords =
    new HashSet<string>(File.ReadLines("C:\stopwords.txt"), StringComparer.OrdinalIgnoreCase);

稍后您可以查看关键字候选者是否在停用词列表中

If (!stopWords.Contains(candidate)) {
    // We have a keyword
}

HashSets 很快。它们的访问时间为 O(1),这意味着进行查找所需的时间不取决于它包含的项目数。

使用 Regex 可以轻松地查找关键字。

string text = ...; // Load text from DB
MatchCollection matches = Regex.Matches(text, "[a-z]([:']?[a-z])*",
                                        RegexOptions.IgnoreCase);
foreach (Match match in matches) {
    if (!stopWords.Contains(match.Value)) {
        ProcessKeyword(match.Value); // Do whatever you need to do here
    }
}

如果您发现 a-z 对字母的限制太多并且需要重音字母,您可以将正则表达式更改为 @"\p{L}([:']?\p{L})*" .字符类 \p{L}包含所有字母和字母修饰符。

短语比较复杂。您可以尝试先将文本拆分为短语,然后对这些短语应用关键字搜索,而不是在整个文本中搜索关键字。这会同时为您提供一个短语中的关键字数量。

将文本拆分为短语涉及搜索以“.”结尾的句子。要么 ”?”要么 ”!”要么 ”:”。您应该排除单词中出现的点和冒号。

string[] phrases = Regex.Split(text, @"[\.\?!:](\s|$)");

这会搜索标点符号后跟空格或行尾。但我必须承认这并不完美。它可能会错误地将缩写检测为句子结尾。您将不得不进行实验以改进拆分机制。

关于c# - 在字符串中查找关键字和关键短语的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11005687/

相关文章:

c# - 使用 Entity Framework 6 的初始负载和性能问题

c# - 具有通用扩展方法的 AutoMapper 映射

sql - 当给定的列值为零时,如何使用上一行的值?

c# - 创建具有多个 Y 轴(3 个或更多)的图表

c# - .NET 中的模块化系统能够在运行时更改

mysql - 在 MySql 中执行查询时与 only_full_group_by 相关的错误

sql - 在 INNER JOIN 条件下有一个 'OR' 是个坏主意吗?

c++ - 长度未知时如何在 SQL Server 中存储 varbinary(max) 和 varchar(max) 数据(使用 C++ ODBC)

sql - 为什么数据库在更新行时执行删除和插入操作?

sql - 在一个事务 "see"中所做的更改是否相互?