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

时间:2015-04-30 03:48:09

标签: java hash

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

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());



            }

        }
       }
     }

任何帮助将不胜感激

3 个答案:

答案 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);
    }