#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 и строкой, которую вы хотите выполнить поиск, и он вернет карту, содержащую проценты соответствующие записи в вашей исходной карте.