Итерация и сравнение значений на картеC ++ - PullRequest
0 голосов
/ 24 октября 2018

Я написал программу на c ++ 17 с использованием библиотеки boost :: filesystem, которая принимает путь в качестве аргумента и возвращает карту:

map<string, vector<string>>

, где каждый ключ является каталогом (boost:: filesystem :: path преобразуется в строку), и каждый файл в каждом каталоге помещается в вектор значений.

Сначала я создаю вектор путей из пути, заданного в качестве аргумента:

// Method to create vector of paths
vector<path> InToVecsOne(path p, vector<path> v1)
{
  for(auto entry : recursive_directory_iterator(p))
  {
    if(is_directory(entry))
    {
      v1.push_back(entry);
    }
  }
  return v1;
}

Затем я создаю карту, используя вектор следующим образом:

// Function takes a vector of paths and returns map of key-value pair path-vector<string>
map<string,vector<string>> FileMap(vector<path> v1, 
map<string,vector<string>> m, vector<string> v2)
{
  for(auto p : v1)
  {
    // iterate over each entry in path p
    for(auto entry : directory_iterator(p)) 
    {
      if(is_regular_file(entry) == true)
      {
        // add file to vector<string>
        v2.push_back(basename(entry) + " "); 
      }
    }
    // convert path to pathname (DirX) string
    string pathname = basename(p); 
    m.insert(make_pair(pathname, v2));
    v2.erase(v2.begin(), v2.end()); // remove contents after iterating
  }
  return m;
}

Используя мою папку с песочницей в качестве тестового пути, я получаю следующий вывод при печати содержимого моей карты:

DirA: Z X Y 
DirB: Z X Y 
DirBB: X Y YY 
DirC: Z 
DirCC: ZZ X Y YY 

Как заметно, ключи - DirA, DirB, DirBB и т. Д., А также значенияZ, X, Y и т. д.

Теперь я хочу преобразовать вещи так, чтобы мой вывод выглядел следующим образом:

X : DirA, DirB, DirBB, DirCC
Y : DirA, DirB, DirBB, DirCC

и т. д.

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

Я не уверен, что будет проще, или как будет выглядеть второй, и, следовательно, потребуется какой-то совет.

Спасибо.


Расширение:

Следуя комментарию, чтобы создать карту пар имя-путь-путь, я столкнулся с новой проблемой после создания этой новой карты из старойкарта выше.Моя функция выглядит следующим образом:

// Make new map where file is key, and dir is value. m1 is old map, m2 is new map
map<string,vector<string>> FinalMap(map<string,vector<string>> m1, 
map<string,vector<string>> m2, vector<string> dirnames)
{
  // iterate over each key
  for(map<string,vector<string>>::const_iterator it = m1.begin(); it != m1.end(); ++it)
  {
    string dirname = it->first;
    dirnames.push_back(dirname);

    vector<string> files = it->second;
    // iterate over elements in vector<string> files
    for(auto i : files)
    {
      m2.insert(make_pair(i, dirnames));
    }
    dirnames.erase(dirnames.begin(), dirnames.end());
  }
  return m2;
}

Однако теперь мой вывод выглядит следующим образом:

X : DirA
Y : DirA
YY : DirBB
Z : DirA
ZZ : DirCC

Мне нужно, чтобы оно было:

X : DirA, DirB, DirBB

и т. Д.учитывая, что файл X находится в DirA, DirB и DirBB.Поэтому я должен изменить функцию FileMap.

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Ваша попытка сделать, как описано в комментариях, неверна.Это должно выглядеть так:

std::map<std::string, std::vector<std::string>> 
FinalMap(std::map<std::string, std::vector<std::string>>const& folderToFiles)
{
    std::map<std::string, std::vector<std::string>> fileToFolders;

    for (auto const& pr : folderToFiles)
    {
        for (auto const& file : pr.second)
            fileToFolders[file].push_back(pr.first);
    }

    return fileToFolders;
}

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

0 голосов
/ 24 октября 2018

Вы можете использовать boost::bimap вместо std :: map и получить оба Dir -> Файл и Файл -> Dir lookups.

#include <boost/bimap.hpp>
using file_map = boost::bimap<std::string, boost::bimaps::multi_set_of<std::string>>;

Вы бы тогдавставьте пару pathname, filename вместо сбора vector имен файлов для связи с путем.

Обратите внимание, что если вы используете только базовое имя каталога, вы можете получить дубликаты.Храните либо весь путь, либо multi_set_of с обеих сторон.

...