我有这个结构
struct Event {
const string event;
const int order;
Event(const string& _event, const int& _order):event(_event),order(_order) {}
};
struct EventCompare {
bool operator()(const Event& lhs, const Event& rhs)
{
return (lhs.order < rhs.order);
}
};
我想在set
中使用:
set<Event, EventCompare> events;
我知道集合不允许重复。但是,我想将重复项定义为两个具有相等events
structs
实例,无论它们的顺序如何,换句话说,A = B
iffA.event == B.event
。这个定义必须影响集合的工作方式,这意味着,例如,如果集合已经包含Event("holiday", 0)
,则必须忽略Event("holiday", 1)
。
我该怎么做?我尝试添加
if (lhs.event == rhs.event)
return false;
在我的EventCompare
,但这不起作用。使用pair
而不是struct
会有所帮助吗?
如果在您指定的条件下它们被认为是相等的,那么很明显,<
比较的结果将是错误的。一个不比另一个少,它们被认为是平等的。为了与关联容器一起使用,比较运算符只需要指示一个实例是否"小于"另一个实例。由于在这种情况下,它们被认为是平等的,因此任何一方都不比另一方少。
因此:
struct EventCompare {
bool operator()(const Event& lhs, const Event& rhs)
{
if (lhs.event == rhs.event)
return false;
return (lhs.order < rhs.order);
}
};
然而,这并不能解决Event
对象的两个实例具有相同order
,但Event
不同的情况。如果这种情况无法出现,您不必担心。如果可以,只需确定它们的顺序,并相应地设置比较运算符的返回值。
您可以使用的最接近的是:
struct EventCompare {
bool operator()(const Event& lhs, const Event& rhs)
{
if (lhs.event == rhs.event)
return false;
return (lhs.order < rhs.order);
}
};
但是,您要求的比较标准不符合将对象放入std::set
中所需的严格弱排序。
假设您有三个包含以下数据的对象:
obj1 = {"foo", 200}
obj2 = {"bar", 300}
obj3 = {"foo", 400}
如果按照obj1
、obj2
obj3
的顺序将对象添加到集合中,则在集合中将只看到obj1
和obj2
。
如果按照obj2
、obj3
obj1
的顺序将对象添加到集合中,则在集合中将只看到obj2
和obj3
。
您不仅会根据首先将哪个对象添加到集合中而获得集合中的不同对象,甚至根据首先添加到集合中的对象,对象也会以不同的顺序出现。如果你遵循这个策略,我只能看到未来的问题。
我认为您应该重新审视您的要求并寻找更清洁的解决方案。如果没有更深入地了解您要做什么,我就无法提出解决方案。
set
不寻求平等。 它只检查排序。
由于您希望两个事件在event
相同时相等,这意味着两者都不先于另一个事件,在这种情况下,您的比较函数应返回false
。
bool operator()(const Event& lhs, const Event& rhs) const {
return lhs.event != rhs.event && lhs.order < rhs.order;
}
但是,这不起作用,因为它不再定义严格的弱排序,因为您可以有A < B
和B < C
但!(A < C)
A
和C
是否具有匹配的字符串event
但B
的顺序介于A
和C
之间。
所以不,你不能使用集合来存储第二个非排序属性覆盖排序属性的元素。 您必须将排序更改为基于event
,但这样您将无法根据order
查找内容。
您可以使用map
将event
字符串映射到用于将它们存储到set
中的order
值。 然后,您检查地图以查看它是否已经存在,并决定将哪个元素保留在集合中。 否则,使用新条目更新集合和地图。
我似乎错过了一些显而易见的东西。但是,您需要做的就是根据您的要求进行比较吗?
struct EventCompareName
{
bool operator()(const Event& lhs, const Event& rhs)
{
// If you want to compare by event and not order, then do so.
return (lhs.event < rhs.event);
// Rather than comparing by order and not event.
//return (lhs.order < rhs.order);
}
};
std::set<Event, EventCompareName> events;
当然,在某些情况下,您可能还希望按order
进行比较(即使您的问题对该要求绝对没有指示)。在这种情况下:
struct EventCompareNameOrder
{
bool operator()(const Event& lhs, const Event& rhs)
{
if (lhs.event != rhs.event)
return (lhs.event < rhs.event);
return (lhs.order < rhs.order);
}
};
std::set<Event, EventCompareNameOrder> allEvents;