![](/img/trans.png)
[英]Best approach to find a key in more than 1 (multiple) 'std::map's or 'std::set's?
[英]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
}
谢谢您的帮助。
您需要优先处理关键字段比较...仅当最重要的字段相等时,才比较第二重要的字段-如果相等,则比较第三重要的字段,等等。一旦出现不平等,您就返回正确或错误(视情况而定)。 因此,这不是&&
运算,应该是? :
? :
或if
- else
链,如:
return lhs.key1 < rhs.key1 ? true :
rhs.key1 < lhs.key1 ? false :
lhs.key2 < rhs.key2 ? true :
rhs.key2 < lhs.key2 ? false :
...
false;
为了使设备正常运行,必须确保键永远不相等-以便永远不会实际使用last false
。
由于要使operator<
正确执行多个测试非常困难,因此我主张使用tuple
(在这种情况下,使用make_tuple
而不是tie
来实现此make_tuple
,因为我们要处理从函数返回的临时变量):
#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
。
如果您要比较三个成员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
需要一个可以对元素进行排序的比较类。 因此,您的比较函数必须提供类似于less
函子或operator<
行为,即a < b
或a > b
(即b < a
)或a == b
(即!(a < b) && !(a > b)
)
如果我们采用您的比较函数,它将认为Lanes(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());
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.