stl: выборка уникальных названий из векторов (найти все вхождения в вектор 1, которых нет в векторе 2)

77
02 июня 2021, 03:00

Подскажите как лучше сделать следующую задачу:

У меня есть 2 списка (вектора) с путями: filesPathes и excludesPathes. Надо выбрать и записать в новый список (вектор) includesPathes только такие пути к файлам, имена которых присутствуют в путях filesPathes и отсутствуют в путях excludesPathes.

Очень бы хотелось короткое, красивое и быстрое решение :)

Я сделал все через std::find_if и библиотеку <filesystem>, но получилось, как мне кажется, излишне навороченным :(

using strings_t = std::vector<std::string>;
// получить список файлов из папки с файлами для анализа
const strings_t filesPathes = getFilesPathes(folderIn);
const strings_t excludesPathes = getFilesPathes(folderOut);
// выбрать уникальные записи
strings_t includesPathes;
for (const auto &fileIn : filesPathes)
{
    const std::string fileName = std::filesystem::path(fileIn).stem().generic_string();
    const auto res = std::find_if(std::begin(excludesPathes), std::end(excludesPathes), [&fileName](const std::string& path) {
        const std::string fileName2 = std::filesystem::path(path).stem().generic_string();
        return (fileName == fileName2);
    });
    if (res == excludesPathes.cend())
        includesPathes.push_back(fileIn);
}

Особенно смущает, что для каждого пути из filesPathes надо делать поиск по всему excludesPathes, что все таки не очень хорошо.

Думал сделать еще через std::set<std::string> куда разместить все имена файлов из excludesPathes, по скорости наверное это самый оптимальный вариант, но плодить отдельную сущность (множество) как-то не хочется, поскольку задача относительно одноразовая и небольшая. НО! Из любви к искусству хочется наиболее правильный подход.

Такой вопрос - если взять за основу приведенный код, можно ли его силами stl как-то то еще утрамбовать? Может есть в stl функции, которые и должны делать такие задачи - находить пересечения в массивах?

Answer 1

Можно использовать алгоритм set_difference:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using strings_t = std::vector<std::string>;

int main(){
    const strings_t filesPath{"A","B","C"};// = getFilesPaths(folderIn);
    const strings_t excludePath{"B","D"};// = getFilesPaths(folderOut);

    strings_t includePaths;
    std::set_difference(filesPath.begin(), filesPath.end(),
                        excludePath.begin(), excludePath.end(), 
                        std::inserter(includePaths, includePaths.begin()));
    // includePaths: A, C
    return 0;
}
READ ALSO
Как переопределить функцию в шаблоне с++?

Как переопределить функцию в шаблоне с++?

Собственно, имеется шаблонный класс treeЕсть еще класс SomeClass, в котором есть метод show

77
ReadFile теряет данные

ReadFile теряет данные

Есть программно-аппаратный комплекс, состоит из внешнего устройства и ПК с управляющей программойСвязь между устройством и ПК осуществляется...

120
Как убрать анимацию?

Как убрать анимацию?

Здравствуйте, как избавиться от анимации?

91
Iframe emded не загружается на маленьком разрешении

Iframe emded не загружается на маленьком разрешении

На сайте используется следующий код:

77