假设有一个基于拉丁语的晦涩字母表,但有很多变音符号(实际上,我使用的字母表是基于西里尔语的,这本身就很混乱,所以我决定使用一个简单的拉丁语例子)
即使设备支持这种语言,输入也很不方便(你需要经常切换布局,使用组合键等),所以我想让用户只能使用“普通”字符进行输入。 o 信件代表 o 本身,然后ó,ö等。
例如,有一个单词“fóobař”。用户只需输入“foobar”,程序就必须返回“fóobař”条目的一些数据。
我这样做:
public static void main(String[] args) {
HashSet<String> guesses = new HashSet();
String initial = "foobar";
generate(initial, 0, guesses);
System.out.println(guesses);
}
private static void generate(String s, int startFrom, HashSet<String> guesses) {
if (startFrom == s.length() - 1) {
return;
}
guesses.add(s);
for (int i = startFrom; i < s.length(); i++) {
char[] substitutes = getSubstitutes(s.charAt(i));
for (char ch : substitutes) {
String newGuess = replaceCharAt(s, i, ch);
generate(newGuess, i + 1, guesses);
}
}
}
private static char[] getSubstitutes(char ch) {
char[] substitutes;
switch (ch) {
case 'o':
substitutes = new char[] {'ó', 'ö'};
return substitutes;
case 'r':
substitutes = new char[] {'ř'};
return substitutes;
default:
return new char[] {};
}
}
private static String replaceCharAt(String s, int position, char ch) {
return s.substring(0, position) + ch + s.substring(position + 1);
}
也就是说,我递归地生成所有可能的替换:
[foóbar, foobař, fóóbar, foobar, foóbař, fööbař, föóbar,
föobař, fööbar, föóbař, fóóbař, fóöbař, föobar, fóobar,
foöbař, foöbar, fóobař, fóöbar]
然后执行具有多个WHERE条件的数据库查询
有没有比尝试所有可能的值更好的方法呢?编写SQLite函数与REGEXP一起使用会更好吗?
答案 0 :(得分:0)
在数据库方面,创建一个带有单词副本的附加列,但每个字符都转换为其“普通”版本,例如将ó
,ö
等转换为o
。
它实际上可能会更好computed column,但它看起来并不像SQLite支持这一点。
然后您可以对输入的文本执行相同的转换,并查询已添加的列以查找转换后的文本。
示例:强>
Word NormalizedWord
foobar foobar
foöbar foobar
fóóbar foobar
查询:fóöbar
。
规范化查询:foobar
。
然后只需查找NormalizedWord
为foobar
的行(在这种情况下,这将是以上所有内容)。
上述方法是优化运行时间 - 它允许您向NormalizedWord
添加索引,以便快速查找。
为了优化空间使用,您可以只存储单词,并在查找中动态转换,但这需要您查看所有行,无论如何这样做都不允许索引。
通过'即时转换',我的意思是:
SELECT *
FROM Table
WHERE Normalize(Word) = NormalizedInputString