1

我需要根据多个键将一组复制到另一组。键用于共同维护集合中元素的唯一性和顺序。

我的课:

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 
}

您的帮助将不胜感激。

4

5 回答 5

3

由于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

于 2012-09-25T08:52:06.760 回答
3

你需要优先考虑你的关键字段比较......只有当最重要的字段相等时,你才会比较第二个最重要的 - 如果它相等,那么你比较第三个最重要的等等。一旦出现不等式,你就会返回正确或错误。所以,它不是一个&&操作,它应该是? :一个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永远不会实际使用 last 。

于 2012-09-25T08:41:44.183 回答
2

如果要比较三个成员 foo、bar 和 baz,这是比较它们的常用方法:

return lhs.foo < rhs.foo
    || lhs.foo == rhs.foo && (lhs.bar < rhs.bar
                           || lhs.bar == rhs.bar && lhs.baz < rhs.baz);

你看到图案了吗?;)

于 2012-09-25T08:49:10.263 回答
1

class MyLaneConnectionSorter有一个缺陷。

std::set需要一个可以对元素进行排序的比较类。因此,您的比较函数必须提供类似于less仿函数 or的行为operator<,即a < bor a > b(which is b < a) or a == b(which is !(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());
    }
}
于 2012-09-25T08:52:57.863 回答
1

我无法理解您的排序规则,但如果关系是简单的子排序,则代码应如下所示:

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;
于 2012-09-25T08:42:32.200 回答