Как удалить все саб пути из списка?
У меня не много опыта в С++ (и возможно, то что мне нужно можно сделать какими то стандартными методами, но я не нашел).
У меня есть вот такой список путей
C:\\Sessions\\MyFolder
C:\\Sessions\\Calib
C:\\Sessions\\Calib\\2020_04_30_18_02
C:\\Sessions\\Calib\\2020_04_30_18_03
C:\\Sessions\\Calib\\2020_04_30_18_02\\test
C:\\Sessions\\Calib\\777\\folder
Мне нужно их очистить таким образом, чтоб полусилось вот так
C:\\Sessions\\MyFolder
C:\\Sessions\\Calib\\2020_04_30_18_03
C:\\Sessions\\Calib\\2020_04_30_18_02\\test
C:\\Sessions\\Calib\\777\\folder
Эти пути были удалены
C:\\Sessions\\Calibrations\\2020_04_30_18_02
C:\\Sessions\\Calibrations
Так как этот путь C:\\Sessions\\Calibrations суб путь от этого C:\\Sessions\\Calibrations\\2020_04_30_18_02 и собственно этот путь C:\\Sessions\\Calibrations\\2020_04_30_18_02 это суб путь от C:\\Sessions\\Calib\\2020_04_30_18_02\\test.
У этого пути C:\\Sessions\\Calib\\2020_04_30_18_02\\test нет суб пути поэтому он остается в списке.
Как я это сделал
/*static*/ std::vector<std::string> Utils::remove_sub_folders(std::vector<std::string> folderPaths_in)
{
std::vector<std::string> result;
std::vector<std::string> executed_paths;
std::vector<std::string> folder_paths = folderPaths_in;
std::sort(folder_paths.begin(), folder_paths.end());
for each (auto & path in folder_paths)
{
std::vector<std::string> path_split = Utils::split(path, "\\");
for each (auto & compare_path in folder_paths)
{
bool is_have_alredy_processed = false;
for each (auto & processed_path in executed_paths)
{
if (compare_path == processed_path)
{
is_have_alredy_processed = true;
break;
}
}
if (!is_have_alredy_processed)
{
std::vector<std::string> compare_path_split = Utils::split(compare_path, "\\");
int path_split_size = static_cast<int>(path_split.size());
int path_compare_size = static_cast<int>(compare_path_split.size());
if (path != compare_path && path_compare_size >= path_split_size)
{
int min_size = min(path_split_size, path_compare_size);
bool is_equal_begin = true;
for (int i = 0; i < min_size; i++)
{
std::string path_word = path_split[i];
std::string compare_word = compare_path_split[i];
if (path_word != compare_word)
{
is_equal_begin = false;
break;
}
}
if ((!is_equal_begin && path_split_size == path_compare_size))
{
result.push_back(path);
}
}
}
}
executed_paths.push_back(path);
}
return result;
}
я не могу понять как правильно все это заставить работать, но результат, что у меня получается это
C:\Sessions\Calib
C:\Sessions\Calib\2020_04_30_18_02
C:\Sessions\Calib\2020_04_30_18_02\test
Вот так я вызываю этот метод
std::vector<std::string> all_dirs_by_path{
"C:\\Sessions\\MyFolder",
"C:\\Sessions\\Calib",
"C:\\Sessions\\Calib\\2020_04_30_18_02",
"C:\\Sessions\\Calib\\2020_04_30_18_03",
"C:\\Sessions\\Calib\\2020_04_30_18_02\\test",
"C:\\Sessions\\Calib\\777\\folder",
};
std::vector<std::string> final_dirs_by_path = Utils::remove_sub_folders(all_dirs_by_path);
Что я делаю не так?
Ответы (1 шт):
В итоге все решилось вот таким способом
https://stackoverflow.com/a/62511019/5709159
using namespace fs = std::filesystem; // or use boost::filesystem here
static bool is_parent(const fs::path &parent, const fs::path &child) {
auto parent_size = std::distance(parent.begin(), parent.end());
auto child_size = std::distance(child.begin(), child.end());
return child_size > parent_size && std::equal(parent.begin(), parent.end(), child.begin());
}
std::vector<fs::path> remove_sub_folders(std::vector<fs::path> paths) {
std::sort(paths.begin(), paths.end());
std::vector<fs::path> result;
for(auto cur = paths.begin(); cur != paths.end(); ++cur) {
auto next = std::next(cur);
if (next == paths.end() || !is_parent(*cur, *next))
result.push_back(*cur);
}
return result;
}