Java | Создание логических выражений в записях hashMap

У меня есть hashMap, который содержит «термин» как ключ и «список документов» как значения.

Например:

KEY::VALUE
afternoon::Doc2
activities::Doc1, Doc2, Doc3
admissions::Doc1, Doc2, Doc4, Doc5
alternate::Doc5

Мне нужно передать логические выражения терминам и получить соответствующие документы. Это выражение будет передано через другую строковую переменную.

Например:

(afternoon AND activities) OR alternate => Doc2, Doc5
(afternoon AND activities) OR (admissions AND alternate) => Doc2, Doc5
activities AND NOT afternoon = > Doc1, Doc3

Есть ли в Java какие-нибудь функции для таких операций? Любые внешние библиотеки тоже будут работать. Фрагмент кода мне очень поможет, так как мое задание должно быть завтра, и это последний шаг моего решения.

Операции фиксированы / статичны? Или это просто примеры, взятые из какой-то текстовой панели?

zolv 05.05.2018 03:00

Если операции являются фиксированными логическими операциями, вы можете использовать Enums, чтобы сопоставить их с соответствующей логикой.

Haris Nadeem 05.05.2018 03:01

Выражения могут меняться при каждом запуске. Я только что привел здесь пример, чтобы объяснить желаемый результат.

Shreyas SG 05.05.2018 03:04

Если выражения представлены в виде свободного текста, то я думаю, что ваше задание может быть в опасности :( Решение SOme: вы можете использовать некоторую базу данных в памяти (например, H2, sqlite, ...), вы можете использовать Antlr (это сложно сделать относительно быстро) или вы можете написать какой-нибудь простой синтаксический анализатор / оценщик самостоятельно только для AND, OR, NOT.

zolv 05.05.2018 03:06

Это последний шаг. Так что, если это работает только для AND, это тоже нормально. Я могу сдать и получить оценки за остальную часть моей работы. Но без этой последней части мое задание будет неполным.

Shreyas SG 05.05.2018 03:09
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
199
2

Ответы 2

Просмотрите значения карты и найдите все ключи, соответствующие этому значению, чтобы создать Map<String, Set<String>>, где, например, ключ. Doc1 и значение, например. мероприятия, входные билеты. Представьте каждое выражение как Predicate<Set<String>>, который просматривает набор терминов и решает, соответствует ли оно выражению.

Сейчас,

map.entrySet().stream().filter(e -> expression.test(e.getValue())).map(Entry::getKey).collect(Collectors.toList());

возвращает список документов, соответствующих выражению термина

Я думаю, что использование предикатов здесь - самая простая часть. Ключевым моментом в задаче является преобразование произвольного текста в цепочку предикатов.

zolv 05.05.2018 03:23

@zolv Я предполагаю, что проблема уже решена, например. у него длинный список предикатов, и он может жестко их запрограммировать.

Vitruvie 05.05.2018 03:25

На мой взгляд, вы хотите добиться объединения и пересечения элементов списка для логических выражений. Вы можете написать собственный метод, например

    public Set<Doc> andOp(Set<Doc> list1, Set<String> Doc) {
    if (list1.isEmpty() || list2.isEmpty())
        return new HashSet<>();

    Set<Doc> result = new HashSet<>();
    Iterator<Doc> it = list1.iterator();
    while( it.hasNext()) {
        Doc Doc1 = it.next();
        if (list2.contains(Doc))
            result.add(Doc);
    }
    return result;
}

public Set<Doc> orOp(Set<Doc> list1, Set<Doc> list2) {
    if (list1.isEmpty()) return list2;
    if (list2.isEmpty()) return list1;

    Set<Doc> result = new HashSet<>();

    result.addAll(list1);
    result.addAll(list2);
    return result;
}

Таким образом, результирующее выражение для (полдень И деятельность) ИЛИ (поступление И допуск) будет выглядеть следующим образом:

Set<Doc> doc1 = andOp(map.get("activities"), map.get("afternoon"));
Set<Doc> doc2 = andOp(map.get("admissions"), map.get("admissions"));
doc1 = orOp(doc1, doc2);

Другие вопросы по теме