【问题标题】:Iterate and compare values in map<string, vector<string>> c++在 map<string, vector<string>> c++ 中迭代和比较值
【发布时间】:2018-10-24 09:03:35
【问题描述】:

我使用 boost::filesystem 库在 c++17 中编写了一个程序,该库将路径作为参数并返回一个映射:

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.重写map方法,或者 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。

【问题讨论】:

  • 你有一个目录到文件名的映射。您需要文件名到目录的映射。差不多就是这样。
  • 您需要什么目录文件的有序映射?你确定你没有尝试优化错误的东西吗?
  • @WhozCraig 我知道你的意思,但我一直在构思该解决方案的外观。
  • 不知道是什么断开了它。最简单的解决方案是保留您现在拥有的所有内容,然后枚举文件夹映射到文件向量,并且对于每个文件夹中的每个文件名,将该文件名/文件夹对填充到另一个字符串映射到 vector ,这一次表示映射到包含它们的文件夹的文件名。结果应该是你所寻求的。
  • @WhozCraig 感谢您的建议。请参阅我所做的编辑。我现在遇到的问题是,当我使用目录名称填充 vector 时,它只使用 push_back(dirname) 添加一个目录......我想我需要更改算法。

标签: c++ dictionary boost boost-filesystem


【解决方案1】:

您尝试按照 cmets 中的说明进行操作是不正确的。它应该是这样的:

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;
}

就是这样。这将枚举文件夹到文件的每个映射并创建文件到文件夹的新映射。我很确定,就是您要找的东西。

【讨论】:

  • 非常感谢,是的,这正是我想要的。
  • 这样容易多了
【解决方案2】:

您可以使用 boost::bimap 代替 std::map,并获取 Dir -> File 和 File -> Dir 查找。

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

然后您将插入 pathname, filename 对,而不是收集文件名的 vector 以与路径关联。

请注意,如果您只使用目录的基本名称,则可能会出现重复。存储整个路径,或在两侧存储multi_set_of

【讨论】:

  • 感谢您的建议。直到现在才知道 bimap,并意识到它可能节省了我的时间。但是,我时间不多,会尽量避免学习 bimap atm 的文档。
  • @Mattia 如果你有boost::bimap&lt;dir, multi_set_of&lt;file&gt;&gt; fmap,那么fmap.left 就像std::multi_map&lt;dir, file&gt;,而fmap.right 就像std::map&lt;file, dir&gt;。这就是你需要知道的全部
  • 谢谢!现在只是在考虑使用多图。
  • 一个更简单的解决方案是填充一个单独的set&lt;string, vector&lt;string&gt;&gt; .. 或者理想情况下是一个multiset&lt;string, string&gt;,这实际上让你非常接近bimap 正在做的事情。 bimap 有其优势(特别是在空间要求方面),但使用起来有点困难。
  • @LightnessRacesinOrbit 我更喜欢bimap 而不是一对maps,因为它会自动保持双方同步
猜你喜欢
  • 2019-01-30
  • 2013-12-18
  • 2020-01-26
  • 2023-03-15
  • 1970-01-01
  • 2015-12-05
  • 2016-01-12
  • 2018-01-06
  • 1970-01-01
相关资源
最近更新 更多