std::set_interaction在两个完全不同的容器上
std::set_intersection on two completely different containers
我有一个简单的要求,需要从另一个向量中的字符串主列表中查找一个向量的字符串出现情况。一开始我很容易做到:
vector<string> custom_list;
set<string> master_list;
vector<string> target_list;
std::sort(custom_list.begin(), custom_list.end());
std::set_intersection(custom_list.begin(), custom_list.end(), master_list.begin(),
master_list.end(), back_inserter(target_list));
这很好用。但后来发现master列表中的每个字符串都与一个标识符相关联。我希望我可以使用std::set_intersection,这样我就可以使用target_list中相交的元素作为索引来获取它们的标识符。实际上,我想我应该把master_list改成一张地图,就像这样:
map<string, SomeCustomId> master_list;
并且能够做一些类似的事情:
auto I_want_this_id = master_list[target_list[0]);
但现在,即使我编写了自己的比较函数,我也不确定是否可以使用set_interaction来比较两个完全不同的容器(custom_list,一个向量和master_list,一个映射(。类似于:
struct mycomparer {
bool operator()(string const& lhs, pair<string, SomeCustomId> const& rhs) {
return lhs == rhs.first;
}
};
这不太奏效(我遇到了各种编译器错误(,而且凭直觉,我也觉得有些不对劲
有没有更好的方法来完成我想要做的事情?
std::set_intersection
期望比较器在lhs < rhs
的情况下返回true
,而不是在lhs == rhs
的情况下。它还必须能够比较它的两个参数,而不考虑顺序(毕竟,确定参数是否等效是由(!comp(a, b) && !comp(b, a))
完成的(。
因此,你会想要类似的东西
struct mycomparer {
bool operator()(string const& lhs, pair<string const, SomeCustomId> const& rhs) {
return lhs < rhs.first;
}
bool operator()(pair<string const, SomeCustomId> const& lhs, string const& rhs) {
return lhs.first < rhs;
}
};
演示。
编辑:更新了演示代码,包括所有必要的标题。(缺少<iterator>
和<string>
。它们可能被GCC中的其他标头包含,但没有被VC++包含。(
VC++2012在进行调试构建时,似乎对提供的谓词运行了一些额外的测试。这会导致编译失败,并出现类似error C2664: 'bool mycomparer::operator ()(const std::pair<_Ty1,_Ty2> &,const std::string &)' : cannot convert parameter 1 from 'std::basic_string<_Elem,_Traits,_Alloc>' to 'const std::pair<_Ty1,_Ty2> &'
的错误。(一旦修复了头文件并切换到旧的初始化风格,它在发布版本中对我来说编译得很好。(
为了解决这个问题,提供operator ()
的过载,采用所有四种可能的参数组合:
struct mycomparer {
bool operator()(string const& lhs, pair<string const, SomeCustomId> const& rhs) {
return lhs < rhs.first;
}
bool operator()(pair<string const, SomeCustomId> const& lhs, string const& rhs) {
return lhs.first < rhs;
}
bool operator()(string const& lhs, string const& rhs) {
return lhs < rhs;
}
bool operator()(pair<string const, SomeCustomId> const& lhs,
pair<string const, SomeCustomId> const& rhs) {
return lhs.first < rhs.first;
}
};
编辑2:如果你可以使用Boost.Lange,那就容易多了。简单地说:
boost::set_intersection(custom_list,
master_list | boost::adaptors::map_keys,
back_inserter(target_list));
不需要自定义谓词,而且可读性很强。演示。
算法实际上并不关心容器。他们关心迭代器,只要这两种容器类型都满足算法的迭代器要求,并且元素类型与比较器匹配,兼容性就不会成为问题。
所以,从根本上说,你所做的一切都是可以的
不过,您需要更正比较器中的逻辑;operator()
应该实现一个小于谓词。而且,正如T.C.所指出的,您需要显式地实现反向比较,因为元素类型不能隐式地相互转换。
- 如何在C++中从两个单独的for循环中添加两个数组
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- 如何返回一个类的两个对象相加的结果
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 两个字符串在 c++ 中不相等
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 两个文件使用彼此的功能-如何解决
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 如何确保在使用基于布尔值的两个方法之一调用方法时避免分支预测错误
- 停止cmake target_link_libraries将插件中静态库的两个对象文件链接到静态库本身
- 将fold表达式与std::一起用于两个元组
- 如何在C++中比较两个char数组
- 给定两个偶数,求出它们之间所有偶数的平方和
- 比较两个大小不等的映射c++
- C++需要帮助从用户那里获得一个整数,并确保它在另外两个整数之间
- 如何在for循环中包含两个索引值的测试条件
- 在声明中合并两个常量"std::set"(不是在运行时)
- 如何使用OpenMP并行这两个循环