在 map<string, vector<string>> c++ 中迭代和比较值
Iterate and compare values in map<string, vector<string>> c++
我用 c++17 编写了一个程序,使用 boost::filesystem 库将路径作为参数,returns 一个映射:
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。
您可以使用 boost::bimap
而不是 std::map,并获得目录 -> 文件和文件 -> 目录查找。
#include <boost/bimap.hpp>
using file_map = boost::bimap<std::string, boost::bimaps::multi_set_of<std::string>>;
然后您将插入 pathname, filename
对,而不是收集 vector
文件名与路径关联。
请注意,如果您只使用目录的基本名称,您可能会得到重复的名称。存储整个路径,或在两侧存储 multi_set_of
。
您尝试按照评论中的描述进行操作是不正确的。它应该是这样的:
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;
}
就是这样。这会枚举文件夹到文件的每个映射,并创建一个新的文件到文件夹的映射。我很确定,这就是您要找的东西。
我用 c++17 编写了一个程序,使用 boost::filesystem 库将路径作为参数,returns 一个映射:
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。
您可以使用 boost::bimap
而不是 std::map,并获得目录 -> 文件和文件 -> 目录查找。
#include <boost/bimap.hpp>
using file_map = boost::bimap<std::string, boost::bimaps::multi_set_of<std::string>>;
然后您将插入 pathname, filename
对,而不是收集 vector
文件名与路径关联。
请注意,如果您只使用目录的基本名称,您可能会得到重复的名称。存储整个路径,或在两侧存储 multi_set_of
。
您尝试按照评论中的描述进行操作是不正确的。它应该是这样的:
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;
}
就是这样。这会枚举文件夹到文件的每个映射,并创建一个新的文件到文件夹的映射。我很确定,这就是您要找的东西。