2014-02-28 85 views
0

假设有其基于拉丁但有很多的变音符号(一个不起眼的字母返回,可以从给定的字符串中产生的所有的话实际上,字母表我是基于西里尔工作,这就够了混乱本身,所以我决定用一个制作好的拉丁例子去做)。通过添加附加符号

即使设备支持这种语言,输入也不方便(您需要经常切换布局,使用组合键等),所以我想让用户只能使用“普通”字符输入。 Ø信将代表Ø本身,然后óö

例如,有一个词 “Foobar的”。用户只能输入“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

如果你只找到所有组合只是为了配合一些关键字,你应该比较规范它,然后做比较 – sidgate

+0

@ sidgate请你解释正常化位,我不明白。 – Doghouse87

回答

0

在数据库方面,创建你的话的副本的附加列,但每个字符转换成它的“普通”版本,例如转换óö等来o

它实际上可能是更好的computed column,但它并不像SQLite支持这虽然。

然后,你可以简单地做对输入的文本相同的转换,和查询添加列转换的文本。

实施例:

Word  NormalizedWord 
foobar foobar 
foöbar foobar 
fóóbar foobar 

查询:fóöbar

规范化的查询:foobar

然后,只需查找NormalizedWordfoobar(在此情况下所有上述内容)的行。


上述方法是优化运行时间 - 它可以让你的索引添加到NormalizedWord允许快速查找。

为了优化空间使用率,您可以只存储单词,并在查找过程中进行即时转换,但这需要您查看所有行,因为这样做不允许索引。

通过“转换上飞”,我的意思是这样的:

SELECT * 
FROM Table 
WHERE Normalize(Word) = NormalizedInputString 
+0

非常感谢!为什么我自己没有想到这个?缺点是,这将使我的数据库规模增加一倍 - 对于Android来说,这是一个相当考虑的因素。 – Doghouse87

+0

@ Doghouse87事实上,尽管我不认为你真的可以解决这个问题,除非你愿意在运行时间方面牺牲很多。我编辑了一些我的答案来阐述。 – Dukeling

+0

非常感谢您的帮助。我想我可以在首次启动时以编程方式填充NormalizedWord列。这样用户不会被更重的.apk文件吓到。之后 - 谁在乎大小:) – Doghouse87