Поиск ключей на карте

#java #search #sortedmap

#java #Поиск #сортированная карта

Вопрос:

Я использую SortedMap для сохранения сопоставлений между строковыми ключами и ArrayList для значения. Ключи — это простые строки, состоящие из нескольких слов. Я хочу получить все записи, в которых ключ соответствует запросу.

Итак, если у меня есть следующие сопоставления:

 "A B C D E" => ArrayList("hello","hi","howdy")
"A C B"  => ArrayList("hehe","haha","hihi") 
"C B E" => ArrayList("non", "sense")
  

и я запрашиваю «A C», я получаю обратно обе записи, соответствующие «A B C D E» и «A C B», с соответствующими коэффициентами подобия (0,4 и 0,66).

Моя идея состояла в том, чтобы перебирать все ключи с помощью .keySet() . Затем я разделяю запрос на отдельные строки с помощью query.split(» «) и рекурсивно ограничиваю список совпадений, но я не уверен, что это оптимальный способ сделать что-то, и, возможно, в Java не реализована уже существующая «поисковая система».

Мой скретч:

 public HashMap<String,Double> searchTags(String query) {

    HashMap<String,Double> hash = new HashMap<String,Double>();

    double similarity = 0;

    //split tags
    String[] tags = query.split(" ");

    for (String key : this.tagsToUtterance.keySet()) {
        for (String tag : tags) {
            if (key.contains(tag)) {
                System.out.println("ok");
                hash.put(key,similarity);
                similarity = 1 ;
            }
        }
        similarity = similarity/key.split(" ").length;
    }

    return hash;
}
  

Комментарии:

1. Ну, это решение кажется довольно неэффективным. Вы могли бы реализовать пользовательскую структуру данных, в которой вы используете карты?

2. если есть B C X A ключ для A C поиска, должен ли он быть в вашем результате?

3. Кент: да, это тоже должно быть в результате

Ответ №1:

Одна вещь, которую вы могли бы сделать, это сохранить мультимап для ваших ключей («A», «C» и т. Д.) Для сопоставления «A B C D E», получить для каждого поискового запроса все сопоставления и вычислить пересечение всех наборов поисковых запросов. Вот так:

 Set<SearchMap> getMappings(List<String> searchTerms) {
    Set<SearchMap> result = this.getSearchMapForTerm(searchTerms.get(0));

    for(int i=1;i< searchTerms.size(); i  ) {
        Sets.intersection(result, this.getSearchMapForTerm(searchTerms.get(i)));
    }
    return resu<
}
  

Взгляните на API guava collections: http://code.google.com/p/guava-libraries/wiki/GuavaExplained

Это было бы просто быстрое и грязное решение. (добавьте проверки границ и т. Д. …)

Ответ №2:

Этот метод должен выполнить всю работу за вас:

 private Map<Double, Entry<String, ArrayList<String>>> queryMethod(
            Map<String, ArrayList<String>> map, String queryString) {
        Map<Double, Entry<String, ArrayList<String>>> result = new HashMap<Double, Entry<String, ArrayList<String>>>();
        queryString = queryString.replaceAll(" ", "");

        for (Entry<String, ArrayList<String>> entry : map.entrySet()) {
            String key = entry.getKey().replaceAll(" ", "");
            boolean contained = true;

            for (char c : queryString.toCharArray()) {
                if (key.indexOf(c) < 0) {
                    contained = false;
                    break;
                }
            }

            if (contained) {
                double percent = (double) queryString.length()
                        / (double) key.length();
                result.put(new Double(percent), entry);
            }
        }

        return resu<
    }
  

Вызовите метод с вашей SortedMap с парами String-ArrayList и строкой, которую вы хотите выполнить поиск, и он вернет карту, содержащую проценты соответствующие записи в вашей исходной карте.