Основная проблема c: задан текстовый файл в структурированном формате (XML, JSON, CSV, ...) и набор правил в виде (path, [strings, ...])
, где путь описывает, какие элементы (тег XML может встречаться несколько раз, столбец CSV может встречаться несколько раз, ...) из strcutured данных, которые необходимо искать, а strings - это список строк для поиска верните смещения, в которых были найдены совпадения.
Будет специальный код для поиска путей в соответствующем документе. Мне хорошо известно, что не существует общего решения для поиска всех полей, соответствующих выражению пути, поэтому будут выделенные парсеры для XML, CSV и т. Д.
То, что я считаю решенной проблемой, - это сбор данных. алгоритм сравнения строк сам. В зависимости от того, сколько строк ищется, и если они являются литералами или регулярными выражениями, я могу выбрать что-нибудь между простым strcmp, поиском по хеш-таблице, Aho-Corasick или полноценным механизмом регулярных выражений.
Интересно, что Каковы фактические входные данные для алгоритма поиска. Я вижу два способа go здесь.
1) Разобрать структурированные данные и создать список строк для каждого пути, в котором выполняется поиск. Затем запустите поиск для каждого из путей и каждого из струны в нем. Pro: постобработка проста, очень совпадение возвращается именно там, где и должно быть. Минусы: большинство алгоритмов имеют определенные издержки во вспомогательных структурах данных, например, таблица ha sh или автомат. Они будут продублированы для каждого пути. И во-вторых, большинство алгоритмов работают эффективно на одном длинном входе. Но у меня есть несколько коротких входов.
struct SearchRule {
std::string path;
std::vector<std::string> terms;
};
struct SearchInput {
std::string path;
std::vector<std::string_view> pathContents;
};
std::vector<Results> searchAll(std::ifstream& doc, Parser& parser, std::vector<SearchRule>& rules, SearchAlgorithm& algo)
{
std::vector<Results> results;
for (const auto& rule : rules) {
algo.init(rule.terms); // build auxiliarry data structures
SearchInput input = parser.getAllElementsForPath(doc, rule.path));
for (const auto& pathContent : input.pathContents)
results.push_back(algo.run(pathContent);
}
return results;
}
2) Просто запустите поиск по всему документу. Позже я должен проверить все совпадения, где они произошли (поэтому анализ структурированного документа происходит здесь, после поиска). Проверка, находится ли смещение совпадения внутри рассматриваемого тега XML или в правильном столбце CSV. Про и c и минусы кажутся в значительной степени противоположными по сравнению с первым подходом.
std::vector<Results> searchAll(std::ifstream& doc, Parser& parser, std::vector<SearchRule>& rules, SearchAlgorithm& algo)
{
std::vector<std::string> allInputs;
for (const auto& rule : rules)
// flatten all inputs into a single vector
allInputs.insert(std::end(allInputs), std::begin(rule.terms), std::end(rule.terms));
algo.init(allInputs);
std::vector<Result> tempResults = algo.run(doc); // reads whole document
// assume result contains the path name and an offset and length for each match
std::vector<Result> ret = std::copy_if(std::begin(tempResults), std::end(tempResults), std::back_inserter(ret),
[parser, doc](Result result){return parser.isReallyAtPath(result, doc);});
}
Оба примера кода приведены только для иллюстрации и не завершены. Я хорошо знаю, что один или другой, вероятно, работают лучше в зависимости от входного документа.
У меня вопрос, если я пропускаю другой вариант, совершенно другой подход?