Ответ 1
Вам нужно указать нечувствительность к регистру Pattern.compile ( "c",
Образец .CASE_INSENSITIVE )
. Чтобы найти слово с c
в нем, вам нужно использовать matcher.find(). Matcher.matches() пытается сопоставить всю строку.
Я создаю тезаурус, используя HashMap для хранения синонимов.
Я пытаюсь выполнить поиск по словам, основанным на регулярном выражении: метод должен взять строку как параметр и вернуть массив результатов. Здесь мой первый удар по нему:
public ArrayList<String> searchDefinition(String regex) {
ArrayList<String> results = new ArrayList<String>();
Pattern p = Pattern.compile(regex);
Set<String> keys = thesaurus.keySet();
Iterator<String> ite = keys.iterator();
while (ite.hasNext()) {
String candidate = ite.next();
Matcher m = p.matcher(candidate);
System.out.println("Attempting to match: " + candidate + " to " + regex);
if (m.matches()) {
System.out.println("it matches");
results.add(candidate);
}
}
if (results.isEmpty()) {
return null;
}
else {
return results;
}
}
Теперь это не работает, как я ожидал (или, может быть, неправильно использую регулярные выражения). Если у меня есть следующие ключи в hashmap:
cat, car, chopper
затем, вызывая searchDefinition("c")
или searchDefinition("c*")
, я получаю null
.
graph
как необходимый тезаурусу? (только любопытство, так как для этого задания нам предлагается использовать Java Collection Map).Спасибо, Dan
EDIT: Я исправил пример. Это не работает, даже если я использую правильный случай.
Вам нужно указать нечувствительность к регистру Pattern.compile ( "c",
Образец .CASE_INSENSITIVE )
. Чтобы найти слово с c
в нем, вам нужно использовать matcher.find(). Matcher.matches() пытается сопоставить всю строку.
Но, hmm:
(a) Зачем использовать HashMap, если вы намерены всегда искать его последовательно? Это много потраченных накладных расходов, чтобы обрабатывать хеш-ключи и все, когда вы их никогда не используете. Разумеется, более простая идея - простой ArrayList или LinkedList.
(b) Что это связано с тезаурусом? Зачем вам искать тезаурус, используя регулярные выражения? Если я хочу знать синонимы, скажем, "кот", я бы подумал, что я буду искать "кошку", а не "c. *".
Моя первая мысль о том, как построить тезаурус, будет... ну, я думаю, первый вопрос, который я задал бы: "Является синонимом отношения эквивалентности?", т.е. если A является синонимом B, следует, что B является синонимом A? И если A является синонимом B и B является синонимом C, то A является синонимом для C? Предполагая, что ответы на эти вопросы "да", то то, что мы хотим построить, - это то, что делит все слова на языке на множества синонимов, поэтому мы можем сопоставить любое слово в каждом наборе со всеми другими словами этого набора, Так что вам нужно, чтобы взять какое-либо слово, сопоставить его с какой-то точкой нексуса, а затем перейти от этой точки привязки ко всем словам, которые соответствуют ему.
Это было бы просто в базе данных: просто создайте таблицу с двумя столбцами, например "слово" и "токен", каждый со своим собственным индексом. Все синонимы сопоставляются с одним и тем же токеном. Токен может быть чем угодно, если он уникален для любого заданного набора синонимов, например порядковый номер. Затем выполните поиск данного слова, найдите связанный токен, а затем получите все слова с этим токеном. Например, мы могли бы создавать записи с (большими, 1), (большими, 1), (гигантскими, 1), (cat, 2), (кошачьим, 2) и т.д. Найдите "большой" , и вы получите 1, затем найдите 1, и вы получите "большой" , "большой" и "гигантский".
Я не знаю ни одного класса во встроенных сборниках Java, который делает это. Самый простой способ, который я могу придумать, - создать две скоординированные хеш-таблицы: одну, которая сопоставляет слова с токенами, а другая - сопоставляет токены массиву слов. Таким образом, таблица 1 может иметь большие → 1, большие → 1, гигантские → 1, cat- > 2, feline- > 2 и т.д. Затем таблица 2 отображает 1 → [большой, большой, гигантский], 2- > [cat, feline] и т.д. Вы просматриваете первую таблицу, чтобы сопоставить слово с токеном, а во втором - сопоставить этот токен со списком слов. Это неуклюже, потому что все данные хранятся избыточно, может быть, есть лучшее решение, но я не получаю его от головы. (Ну, было бы легко предположить, что мы будем последовательно искать весь список слов каждый раз, но производительность будет сосать, поскольку список стал большим.)
Это регулярное выражение, которое вы используете?
Метод Matcher.matches() возвращает true только в том случае, если вся входная последовательность соответствует выражению (из Javadoc), поэтому в этом случае вам нужно будет использовать "c.*"
, а не "c*"
, а также соответствующий регистр бесчувственно.
Регулярные выражения чувствительны к регистру. Вы хотите:
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Похоже, вы неправильно используете свои регулярные выражения. "c" будет соответствовать только нижнему регистру c, а не верхнему регистру.
Тем не менее, я предлагаю вам изучить встроенную базу данных с возможностями полнотекстового поиска.
Отвечая Джею "Но Хм" выше,
(я бы добавил комментарий, но не имел репутации.)
Поиск его последовательно делает это медленным способом. Делать это с регулярными выражениями - это спуститься в безумие. Выполнение этого с помощью базы данных - это программирование. Конечно, если ваш набор данных был массивным, что может потребоваться, но помните, что "для этого задания нам предлагается использовать карту Java Collection". Мы должны выяснить, как правильно использовать эту коллекцию java.
Причина не очевидна, потому что это не одна коллекция. Это два. Но это не две карты. Это не ArrayList. Отсутствует набор. Это карта для наборов синонимов.
Набор < Строка > позволит вам создавать списки синонимов. Вы можете сделать столько, сколько хотите. Хорошим примером может служить два набора синонимов. Это не Set ArrayList, потому что вы не хотите дублировать слова.
Карта < String, Set <String → > позволит вам быстро найти свой путь от любого слова до его синонима.
Создайте свои наборы. Затем постройте карту. Напишите вспомогательный метод для построения карты, которая берет карту и набор.
addSet (карта < String, Set <String> map, Set <String> newSet)
Этот метод просто петли newSet и добавляет строки к карте в качестве ключей и ссылку на newSet в качестве значения. Вызов addSet один раз для каждого набора.
Теперь, когда вы создаёте структуру данных, мы сможем найти материал. Чтобы сделать это немного более надежным, не забудьте очистить свой ключ поиска до поиска. Используйте trim(), чтобы избавиться от бессмысленных пробелов. Используйте toLowerCase(), чтобы избавиться от бессмысленной капитализации. Вы должны были сделать оба из этих данных синонимов до (или пока) построения наборов. Сделайте это и кому нужны регулярные выражения для этого? Этот способ намного быстрее и, что важнее, безопаснее. Регулярные выражения очень мощные, но могут быть кошмаром для отладки, когда они идут не так. Не используйте их только потому, что считаете, что они классные.