【问题标题】:multimap with custom keys - comparison function带有自定义键的多图 - 比较功能
【发布时间】:2014-08-11 09:42:52
【问题描述】:
bool operator<(const Binding& b1, const Binding& b2)
{
    if(b1.r != b2.r && b1.t1 != b2.t1)
    {
        if(b1.r != b2.r)
            return b1.r < b2.r;
        return b1.t1 < b2.t1;
    }
    return false;
}

我有一个像上面这样的比较功能。基本上,如果其中一个属性匹配,我需要认为对象相等。我正在为我的多图使用这个比较函数,它的键是“绑定”对象。 我面临的问题是 lower_bound 和 upper_bound 函数返回指向有效对象的相同迭代器。例如 (t1 = 1, r = 2) 已经在地图中,当我尝试使用 (t1 = 1, r = 2) 在地图中搜索它时,我得到与上界和下界函数的返回值相同的迭代器.

比较功能有什么问题吗?有没有办法计算一个函数,即使只有一个字段匹配,我仍然可以确保对象是等效的? upper_bound 迭代器不应该返回超过

的对象吗?

【问题讨论】:

  • 比较需要是严格的弱排序。你所描述的听起来不像。

标签: c++ iterator multimap comparison-operators


【解决方案1】:

map 或 multimap 的比较器应在键集之间表达严格的弱排序关系。您的要求“如果只有一个字段匹配,则两个对象是等效的”不能是这样的关系。拿这三把钥匙:

1: r=1, t1=10
2: r=1, t1=42
3: r=2, t1=42

显然,键 1 和 2 是等价的,因为它们具有相同的 r。同样,由于 t1 相同,所以 2 和 3 是等价的。这意味着,1 和 3 也必须是等价的,尽管它们没有匹配的字段。

因此,在这些情况下,所有个可能的键都必须是等效的,这意味着您根本没有任何排序,并且多映射不是正确的选择。

对于您的情况,您会想到 Boost.MultiIndex。然后,您可以为 rt1 设置两个单独的索引,并分别对这两个索引执行 lower_boundupper_boundequal_range 搜索。

【讨论】:

    【解决方案2】:

    你删除冗余代码后的比较函数可以重写为

    bool operator<(const Binding& b1, const Binding& b2)
    {
        if(b1.r != b2.r && b1.t1 != b2.t1)
        {
            //if(b1.r != b2.r) // always true
                return b1.r < b2.r;
            //return b1.t1 < b2.t1;  // Never reached
        }
        return false;
    }
    

    或者根据德摩根定律

    bool operator<(const Binding& b1, const Binding& b2)
    {
        if(b1.r == b2.r || b1.t1 == b2.t1) return false;
        else return b1.r < b2.r;
    }
    

    这不保证a &lt; c 如果a &lt; bb &lt; c

    例如:绑定(r, t): a(3, 5), b(4, 6), c(5, 5)

    如果您的比较函数不符合上述条件,您可能会得到奇怪的结果。 (如果库不健壮,在某些情况下包括无限循环)

    【讨论】:

    • 在这种情况下,当我想让对象等效时,即使其中一个键相等,什么是好的数据结构
    • 正如Arne Mertz 在他的回答中建议的那样,如果 Boost.MultiIndex 符合您的要求,它是一个不错的选择。另一种选择是保留两个单独的多图,其中 1 的比较函数仅使用 r,而另一个仅使用 t 比较。然后你可以找到它们的范围,并为所有键使用交集(min)。
    【解决方案3】:

    如果 rs 或 ts 由于 if() 子句中的 &amp;&amp; 匹配,您的比较函数将返回 false。你的意思是|| 吗?将&amp;&amp; 替换为|| 将为您提供一个有效的比较函数,该函数首先通过r 字段进行比较,然后是t 字段。

    请注意,std::pair 已经有一个比较功能可以做到这一点。

    您的代码下方的文字虽然指出:

    基本上,如果对象的一个​​属性匹配,我需要认为对象相等

    你不能这样做,因为它不会传递(因此你不会有严格的排序)。

    if 块的内部有另一个 if 肯定是真的,因为 &amp;&amp; 子句意味着双方都是真的。

    【讨论】:

    • 比较不会是“有效的”,因为标准要求比较器表达严格的弱排序,这里不是这种情况(见其他答案)
    • 是的,当然它不是严格的排序,它在那里提到。我只是质疑海报是否意味着||因为 && 没有意义
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-22
    • 1970-01-01
    • 2021-01-01
    • 1970-01-01
    • 2017-06-07
    相关资源
    最近更新 更多