在哈希映射中搜索 Java 中的多个键

Searching through a hash map for multiple keys in Java

我想弄清楚如何在一些用户输入中搜索来自名为 Synonym 的哈希映射的多个 keywords.The 关键字。所以基本上我输入一些句子,如果句子包含一个或多个关键字或关键字同义词,我想调用一个解析文件方法。到目前为止,我只能搜索一个关键字。我一直在尝试获取用户输入,这可能是一个长句或只是一个包含关键字的单词,并在哈希映射键中搜索该匹配的单词。例如,如果哈希映射是

responses.put("textbook name", new String[] { "name of textbook", "text", "portfolio" });


        responses.put("current assignment", new String[] { "homework","current work" });

然后用户输入“有作业的教科书的名字是什么”我想搜索文本文件 教科书 当前作业.假设文本文件包含句子 The current assignment is in the second tacle name 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());



            }

        }
       }
     }

任何帮助将不胜感激

您可以对每个 "dictionary entry" 使用一个正则表达式模式,并针对您的输入测试每个模式。根据您的性能要求以及字典和输入的大小,它可能是一个很好的解决方案。

如果您使用的是 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) Input List --> 句子中的溢出词(可能是按顺序排列的)并将其保存在列表示例中 [what,is,the,name,of,textbook,that,has,the,homework ]

2) 关键字列表 --> 您正在使用的 Hashmap 数据库中的所有关键字示例 [test,textbook name,professor office]

现在你必须设置一些标准,你说我可以将句子中最多 3 个词的短语(例如 'name of textbook')作为关键字,为什么这个标准 - 限制处理,否则你会最终检查了很多输入组合。

一旦你有了这个,你就可以检查输入列表和关键字列表中的常见内容是否符合你设置的标准。如果你没有设置标准,那么你可以尝试所有的组合对键 set.Once 你找到一个或多个匹配,输出同义词列表等。

示例检查 [教科书名称] 与您在地图上的所有键。

如果你想反向检查,通过创建同义词列表并检查它来执行相同的过程。

我解决这个问题的两个技巧

1) 定义一组关键字并且不检查值列表,哈希映射结构不适合这样做。在此为冗余数据做好准备。

2) 设置要在此键集中搜索的单词数。最好只保留不同的词。

希望对您有所帮助!

创建一个 list/append 匹配的键。对于给定的示例,当关键字 "textbook" 匹配时将其存储在 "temp" 变量中。现在,继续循环,现在关键字 "current" 匹配,将其附加到变量 temp。所以,现在 temp 包含 "textbook current"。同样,继续将下一个关键字 "assignment" 附加到 "temp" 中。

现在,temp 包含 "textbook current assignment"。

现在最后调用 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);
    }