我正在尝试弄清楚如何搜索多个关键字的一些用户输入。关键字来自名为同义词的哈希映射。所以基本上我输入一些句子,如果句子包含一个或多个关键字或关键字同义词,我想调用一个解析文件方法。到目前为止,我只能搜索一个关键字。我试图获得一个用户输入,这可能是一个长句子或只是一个包含关键字的单词,并搜索该匹配单词的哈希映射键。例如,如果哈希映射是
responses.put("textbook name", new String[] { "name of textbook", "text", "portfolio" });
responses.put("current assignment", new String[] { "homework","current work" });
并且用户输入"有作业的教科书的名称是什么?我想在文本文件中搜索教科书 当前作业。假设文本文件包含句子当前分配在第二个教科书名称ralphy"中。我的意思是我完成了大部分实现,问题是处理多个关键字。有人可以帮我解决这个问题吗?
这是我的代码
private static HashMap<String, String[]> responses = new HashMap<String, String[]>(); // this
public static void parseFile(String s) throws FileNotFoundException {
File file = new File("data.txt");
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
final String lineFromFile = scanner.nextLine();
if (lineFromFile.contains(s)) {
// a match!
System.out.println(lineFromFile);
// break;
}
}
}
private static HashMap<String, String[]> populateSynonymMap() {
responses.put("test", new String[] { "test load", "quantity of test","amount of test" });
responses.put("textbook name", new String[] { "name of textbook", "text", "portfolio" });
responses.put("professor office", new String[] { "room", "post", "place" });
responses.put("day", new String[] { "time", "date" });
responses.put("current assignment", new String[] { "homework","current work" });
return responses;
}
public static void main(String args[]) throws ParseException, IOException {
/* Initialization */
HashMap<String, String[]> synonymMap = new HashMap<String, String[]>();
synonymMap = populateSynonymMap(); // populate the map
Scanner scanner = new Scanner(System.in);
String input = null;
/*End Initialization*/
System.out.println("Welcome To DataBase ");
System.out.println("What would you like to know?");
System.out.print("> ");
input = scanner.nextLine().toLowerCase();
String[] inputs = input.split(" ");
for (String ing : inputs) { // iterate over each word of the sentence.
boolean found = false;
for (Map.Entry<String, String[]> entry : synonymMap.entrySet()) {
String key = entry.getKey();
String[] value = entry.getValue();
if (input.contains(key) || key.contains(input)|| Arrays.asList(value).contains(input)) {
found = true;
parseFile(entry.getKey());
}
}
}
}
任何帮助将不胜感激
答案 0 :(得分:0)
您可以为每个“词典条目”使用单个正则表达式模式,并根据您的输入测试每个模式。根据您的性能要求以及字典和输入的大小,这可能是一个很好的解决方案。
如果你使用的是java 8,试试这个:
public static class DicEntry {
String key;
String[] syns;
Pattern pattern;
public DicEntry(String key, String... syns) {
this.key = key;
this.syns = syns;
pattern = Pattern.compile(".*(?:" + Stream.concat(Stream.of(key), Stream.of(syns))
.map(x -> "\\b" + Pattern.quote(x) + "\\b")
.collect(Collectors.joining("|")) + ").*");
}
}
public static void main(String args[]) throws ParseException, IOException {
// Initialization
List<DicEntry> synonymMap = populateSynonymMap();
Scanner scanner = new Scanner(System.in);
// End Initialization
System.out.println("Welcome To DataBase ");
System.out.println("What would you like to know?");
System.out.print("> ");
String input = scanner.nextLine().toLowerCase();
boolean found;
for (DicEntry entry : synonymMap) {
if (entry.pattern.matcher(input).matches()) {
found = true;
System.out.println(entry.key);
parseFile(entry.key);
}
}
}
private static List<DicEntry> populateSynonymMap() {
List<DicEntry> responses = new ArrayList<>();
responses.add(new DicEntry("test", "test load", "quantity of test", "amount of test"));
responses.add(new DicEntry("textbook name", "name of textbook", "text", "portfolio"));
responses.add(new DicEntry("professor office", "room", "post", "place"));
responses.add(new DicEntry("day", "time", "date"));
responses.add(new DicEntry("current assignment", "homework", "current work"));
return responses;
}
示例输出:
Welcome To DataBase
What would you like to know?
> what is the name of textbook that has the homework
textbook name
current assignment
答案 1 :(得分:0)
我回答了非常类似的问题Understand two or more keys with Hashmaps。但我会更清楚地说明我的观点。在您使用的当前数据结构集中,考虑以下结构
1)输入列表 - &gt;句子中的溢出的单词(可能是有序的)并将其保存在列表示例中[什么,是,名称,教科书,那个,有,作业]
2)关键字列表 - &gt;您使用的Hashmap数据库中的所有键示例[test,textbook name,professor office]
现在你必须设置一些标准,你说我可以用句子中的最多3个单词短语(例子&#39;教科书的名称&#39;)作为关键字,为什么这个标准 - 限制处理,否则你最终会检查很多输入组合。
完成此操作后,您可以检查输入列表和关键字列表中常见的已设置标准。如果您没有设置标准,那么您可以针对密钥集尝试所有组合。一旦找到单个或多个匹配项,输出同义词列表等。
示例检查[教科书的名称]对照地图的所有键。
如果要反向检查,请通过创建同义词列表并进行检查来执行相同的过程。
解决这个问题的两个技巧
1)定义一组关键字,不用值列表检查,哈希地图结构不好用。在此为冗余数据做好准备。
2)按照您要在此键集中搜索的顺序设置多少个单词。最好只保留不同的词语。
希望这有帮助!
答案 2 :(得分:0)
制作一个列表/附加匹配的键。至于给定的例子,当关键字&#34;教科书&#34;匹配将它存储在&#34; temp&#34;变量。现在,继续循环,现在关键字&#34; current&#34;匹配,将此附加到变量temp。所以,现在temp包含&#34;教科书当前&#34;。 Similairly,继续并附加下一个关键字&#34; assignment&#34;进入&#34; temp&#34;。
现在,temp包含&#34;教科书当前分配&#34;。
现在最后调用parseFile(temp)。
这适用于单个或多个匹配。
//Only limitation is the keys are to be given in a ordered sequence , if you want
// to evaluate all the possible combinations then better add all the keys in a list
// And append them in the required combination.
//There might be corner cases which I havent thought of but this might help/point to a more better solution
String temp = "";
//flag - used to indicate whether any word was found in the dictionary or not?
int flag = 0;
for (String ing : inputs) { // iterate over each word of the sentence.
boolean found = false;
for (Map.Entry<String, String[]> entry : synonymMap.entrySet()) {
String key = entry.getKey();
String[] value = entry.getValue();
if (input.contains(key)) {
flag = 1;
found = true;
temp = temp +" "+ key;
}
else if (key.contains(input)) {
flag = 1;
found = true;
temp = temp +" "+ input;
}
else if (Arrays.asList(value).contains(input)) {
flag = 1;
found = true;
temp = temp +" "+ input;
}
}
}
if (flag == 1){
parseFile(temp);
}