如何使用多个键对 std::set 进行排序
how to sort a std::set using more than one key
我需要根据多个键将一个集合复制到另一个集合。键用于共同维护集合中元素的唯一性和顺序。
我的班级:
class LaneConnector {
public:
const Lane* getLaneFrom() const {
return From;
}
const Lane* getLaneTo() const {
return To;
}
private:
Lane* From;
Lane* To;
}
我的函子:
struct MyLaneConectorSorter {
bool operator() (const LaneConnector* rhs, const LaneConnector* lhs) const
{
const Lane* a = lhs->getLaneFrom();
const Lane* b = rhs->getLaneFrom();
bool key1 = a->getLaneID() < b->getLaneID();
bool key2 = a->getLaneParent->ID() < b->getLaneParent->ID();
bool key2 = a->getLaneParent->getParent->ID() < b->getLaneParent->getParent->ID();
//remind you that I NEED the elements to be in ascending order of
//getLaneParent->getParent->ID() ,a->getLaneParent->ID() and then a->getLaneID()
//duplicate elements are the ones which have all three keys same and need to be discarded
return (key1 && key2 && key3); //which dont seem to be working
}
};
以及我的源和源集:
const std::set<LaneConnector*> src = ..... ; //the getter give me a const version
std::set<sim_mob::LaneConnector *, MyLaneConectorSorter> dest;
以及我如何填充它:
for(std::set<sim_mob::LaneConnector*>::iterator it = tempLC.begin(); it != tempLC.end(); it++)
{
dest.insert(*it);//I know I can insert it right at the time of declaration, but keep it like this for now...please
}
您的帮助将不胜感激。
operator<
多个测试相当困难,因此我提倡使用tuple
来执行此操作(在这种情况下使用make_tuple
而不是tie
因为我们正在处理从函数返回的临时):
#include <tuple>
struct MyLaneConectorSorter {
bool operator() (const LaneConnector* lhs, const LaneConnector* rhs) const
{
const Lane* a = lhs->getLaneFrom();
const Lane* b = rhs->getLaneFrom();
auto const* pa = a->getLaneParent();
auto const* pb = b->getLaneParent();
return std::make_tuple(a->getLaneID(), pa->ID(), pa->getParent()->ID()) <
std::make_tuple(b->getLaneID(), pb->ID(), pb->getParent()->ID())
}
这应该有效,如果您的编译器尚未提供它们,您也可以从 Boost 获得tuple
和make_tuple
。
优先考虑关键字段比较...只有当最重要的字段相等时,你才会比较第二重要的字段——如果相等,那么你比较第三重要的字段,等等。 一旦出现不平等,你就会适当地返回真或假。 因此,它不是一个&&
操作,它应该是? :
或if
- else
链,如下所示:
return lhs.key1 < rhs.key1 ? true :
rhs.key1 < lhs.key1 ? false :
lhs.key2 < rhs.key2 ? true :
rhs.key2 < lhs.key2 ? false :
...
false;
要使集合正常运行,必须确保键永远不会相等 - 以便永远不会实际使用最后一个false
。
如果你有三个成员foo,bar和baz要比较,这是比较它们的常用方法:
return lhs.foo < rhs.foo
|| lhs.foo == rhs.foo && (lhs.bar < rhs.bar
|| lhs.bar == rhs.bar && lhs.baz < rhs.baz);
你看到模式了吗?;)
我在理解您的排序规则时遇到问题,但如果关系是简单的子排序,那么代码应如下所示:
if (a->getLaneID() < b->getLaneID())
return true;
else if (a->getLaneID() == b->getLaneID())
{
if (a->getLaneParent->ID() < b->getLaneParent->ID())
return true;
// etc...
}
return false;
你的class MyLaneConnectionSorter
有缺陷。
std::set
需要一个可以对元素进行排序的比较类。所以你的比较函数必须提供类似于函子或operator<
less
的行为,即a < b
或a > b
(这是b < a
)或a == b
(这是!(a < b) && !(a > b)
)
如果我们采用您的比较函数,它将认为车道 (6, 5, 4) 和 (7, 3, 4)(格式为 (PPID, PID, ID)) 相等,因为两者都不比另一个小。所以你需要像这样比较:
if (a->getLaneParent->getParent->ID() < b->getLaneParent->getParent->ID()) return true;
else if (a->getLaneParent->getParent->ID() > b->getLaneParent->getParent->ID()) return false;
else {
if (a->getLaneParent->ID() < b->getLaneParent->ID()) return true;
else if (a->getLaneParent->ID() > b->getLaneParent->ID()) return false;
else {
return (a->getLaneID() < b->getLaneID());
}
}
- 二叉排序树无法编译
- 仅使用绝对值对数组进行排序,并在C++中显示实际值
- 如何将标准::矢量插入具有自定义排序功能的 std::set 中
- 存储在 std::map/std::set 中,与在存储所有数据后对向量进行排序
- 将排序范围插入 std::set 并带有提示
- std::set<myClass*>排序
- 使用不同的比较函数对 std::set 进行排序和重复检查
- 为什么对排序向量进行的二进制搜索比STD :: SET FIND慢
- 排序 std::set 使用 operator() 对插入进行排序
- 如何使用多个键对 std::set 进行排序
- 在每种情况下都执行“std::set”对元素进行排序
- 分段故障:SET C++11中的二次排序
- C++std::set的排序输出
- 我们在 std::map 或 std::set 中有什么样的排序
- 如何在另一个类数据成员上定义“std::set”排序
- 为什么在声明std::set时需要重复排序子程序
- 在C++中对范围(没有重复项)进行排序是 std::vector 和 std::sort 比 std::set 快
- std::set,它有多个排序选项
- 修改c++ std::set中元素中与排序相关的部分
- C++11 std::函数和std::reference包装器,用于对std::set进行排序