我正在尝试提供一种函数,该函数可以为指定的字符串生成可能的数据库匹配,其中大多数这些指定的字符串不能轻易匹配,因为它们处于不同的命名形式,例如电影的首字母缩略词。数据库值仅在此阶段使用全名。到目前为止我所提出的是一个函数,它生成一个模式,每个单词的首字母由数据库候选者分隔。*
pkgName matched: The.Fighter.2010.DVDRip.XviD.AC3-TiMPE, for pattern: .*0.*M.*, title: 007 Moonraker pkgName matched: The.Fighter.2010.DVDRip.XviD.AC3-TiMPE, for pattern: .*1.*A.*M.*, title: 12 Angry Men pkgName matched: The.Fighter.2010.DVDRip.XviD.AC3-TiMPE, for pattern: .*3.*, title: 300 pkgName matched: The.Fighter.2010.DVDRip.XviD.AC3-TiMPE, for pattern: .*A.*P.*, title: A Prophet pkgName matched: The.Fighter.2010.DVDRip.XviD.AC3-TiMPE, for pattern: .*A.*, title: Adaptation pkgName matched: The.Fighter.2010.DVDRip.XviD.AC3-TiMPE, for pattern: .*A.*, title: Adventureland pkgName matched: The.Fighter.2010.DVDRip.XviD.AC3-TiMPE, for pattern: .*A.*, title: Amelie pkgName matched: The.Fighter.2010.DVDRip.XviD.AC3-TiMPE, for pattern: .*A.*P.*, title: American Psycho
问题是这种方法产生了太多不需要的建议匹配(在我之前的例子中都是不需要的)。任何人都可以建议一个更好的方法,以削减不必要的这些匹配?正则表达式是否适用于此?
public ArrayList<Movie> databaseMatches(String pkgName) {
Connection conn = getConnection();
ArrayList<Movie> dbMatches = new ArrayList<Movie>();
try {
for (Movie dbTitle : getDatabaseMovies(conn)) {
Pattern p = Pattern.compile(createTitlePattern(dbTitle.getTitle()));
Matcher m = p.matcher(pkgName);
if (m.find()) {
System.out.println("pkgName matched: " + pkgName + ", for pattern: " + createTitlePattern(dbTitle.getTitle()) + ", title: " + dbTitle.getTitle());
dbMatches.add(dbTitle);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return dbMatches;
}
private String createTitlePattern(String dbTitle) {
// System.out.println("dbTitle: " + dbTitle + "split(' ')");
String titleParts[] = dbTitle.split(" ");
String searchPattern = ".*";
for (int i = 0; i < titleParts.length; i++) {
char c = titleParts[i].charAt(0);
searchPattern += (c + ".*");
}
// System.out.println("pattern produced: " + searchPattern);
return searchPattern;
}
编辑:我遇到过每个首字母缩略词字母之间带有各种字符的字符串实例,所以我认为这种模式是合适的。
答案 0 :(得分:1)
.*x.*y.*z.*
形式的正则表达式表示“我们可以按顺序找到x,y,z的任何字符串,由任意数量的任何字符分隔”,并且没有迹象表明x,y或者z必须是单个单词的第一个字母。
在首字母缩写之前,你必须把一个字符类放在你期望的所有字符分隔符上。
您可以使用预定义的\W
字符类将所有非单词字符视为字词分隔符。
单词字符为A-Z
,a-z
,0-9
和_
(下划线)。所有其他人都是非文字字符。
如果此功能适合您,请将".*"
替换为".*\W"
。
答案 1 :(得分:1)
由于您对数据格式的标准很少,因此您可能需要使用稍微不同的方法,这可能会也可能不会,这取决于应用程序的数据/吞吐量需求的大小。一个建议是从全文匹配开始,只有在未能产生结果的情况下才会转移到更广泛的搜索或其他变体。
使用前面的示例,您可以从完整的关键字搜索开始:
.*American.*Psycho.*
如果不能产生结果,请尝试纯粹的首字母缩略词搜索
.*AP.*
如果单个关键字搜索失败
.*((American)|(Psycho)).*
然后进入混合关键字/缩写搜索
.*(A|(American)).*(P|(Psycho))
等。同样,根据搜索运行的速度/运行速度需要多快,这种方法可能会受到严重阻碍。
如果这是不可接受的,您可以尝试使用上面的单个“松散”模式,并尽可能尝试允许完整的单词匹配,并最小化关键字之间的分组。
.*(A[merican]*)(.*?)(P[sycho]*)
请注意,我们使用字符类(方括号)而不是常规分组(圆括号),以允许在剩余标题上进行部分匹配。即前一个匹配“Amer.Psy。”。然后根据您获得的匹配,您可以进一步检查分组以消除误报。例如,如果组1仅匹配“A”,则可能期望组2为空,或者仅包含非字母数字,如果不是,则将其视为误报。
答案 2 :(得分:1)
为了匹配不可预测的缩写,您需要使用比First Letters更好的技术。 Stack Overflow上的这篇文章有一些想法,包括用于匹配两个单词之间距离的替代算法: