【问题标题】:std::map, custom key type with sorting only on one variablestd::map,自定义键类型,仅对一个变量进行排序
【发布时间】:2012-07-03 19:08:12
【问题描述】:

我有一个密钥类型:

struct KeyT {
    uint32_t timestamp;

    // example!
    uint32_t a;
    uint32_t b;
    uint32_t c;
    uint32_t d;
    uint32_t e;
    // ...

    bool operator== (const KeyT& key) const
    {
        if(timestamp == key.timestamp && a == key.a && b == key.b && d == key.d && c == key.c && e == key.e)
            return true;
        return false;

    }
    bool operator< (const KeyT& key) const
    {
        if(timestamp < key.timestamp)
            return true;
        else if(timestamp == key.timestamp && a < key.a && b < key.b && c < key.c && d < key.d && e < key.e)
            return true;
        else if(timestamp == key.timestamp && a == key.a && b < key.b && c < key.c && d < key.d && e < key.e)
            return true;
        else if(timestamp == key.timestamp && a == key.a && b == key.b && c < key.c && d < key.d && e < key.e)
            return true;
        else if(timestamp == key.timestamp && a == key.a && b == key.b && c == key.c && d < key.d && e < key.e)
            return true;
        else if(timestamp == key.timestamp && a == key.a && b == key.b && c == key.c && d == key.d && e < key.e)
            return true;
        // ..
        return false;
    }
};

现在,我并不真正关心成员变量 a、b、c、d、e 的排序,我唯一要确保的是地图按时间戳排序。我也刚刚意识到,如果我有两个 KeyT 实例一,二,除了“d”之外一切都相同,那么一

谢谢!

【问题讨论】:

  • 如果你有相同的项目,那么“一
  • 它们不相同,只是成员变量d不同。

标签: c++ map operators std


【解决方案1】:

我认为这可以满足您的需要:

bool operator< (const KeyT& key) const
{
    if(timestamp != key.timestamp) return timestamp < key.timestamp;
    else if ( a != key.a ) return a < key.a;
    else if ( b != key.b ) return b < key.b;
    else if ( c != key.c ) return c < key.c;
    else if ( d != key.d ) return d < key.d;
    else return e < key.e;
}

当您有一个要在可比较的类中排序的变量的优先列表时,这是一个明智但丑陋的模式。

【讨论】:

  • 正是我想要的!我知道我遗漏了一些明显的东西。
  • 很高兴为您服务。我已经写过几次了。顺便说一句,boost::tuple 可以用于这种事情。它在tuple_comparison.hpp 中有一个排序功能,它执行这种优先的、逐个元素的排序。我经常使用它对数据进行快速而肮脏的排序,而无需编写新的类或排序函数。
  • 我会将它打包到std::binary_function 类中并将其添加为模板参数。
  • @Naszta:我不明白这会如何让它变得不那么冗长?
  • @KimSun-wu: this is the reason.
【解决方案2】:

首先,您应该只比较下一个尚未比较的当前键小于,并在return 之后删除else,如下所示:

bool operator< (const KeyT& key) const
{
    if(timestamp < key.timestamp)
        return true;
    if(timestamp == key.timestamp && a < key.a)
        return true;
    if(timestamp == key.timestamp && a == key.a && b < key.b)
        return true;
    if(timestamp == key.timestamp && a == key.a && b == key.b && c < key.c)
        return true;
    if(timestamp == key.timestamp && a == key.a && b == key.b && c == key.c && d < key.d)
        return true;
    if(timestamp == key.timestamp && a == key.a && b == key.b && c == key.c && d == key.d && e < key.e)
        return true;
    // ..
    return false;
}

如果只需要比较时间戳,留下第一个if,其余的删除:

bool operator< (const KeyT& key) const
{
    return timestamp < key.timestamp;
}

当您使用此运算符比较您的密钥时,具有相同时间戳的项目不会被重新排序。

【讨论】:

  • 这也有效,但它是否提供了亚历克斯的答案?
  • @KimSun-wu 不,这只是写相同条件的不同方式。阅读起来可能会更自然一些,因为它可以翻译成人类语言,就像人们倾向于考虑解决排序顺序中的关系一样,但除此之外,两者应该产生相同的结果。
  • 也许只有我一个人,但我发现 Alex 的版本更简单/更易于阅读。
【解决方案3】:

如果您只关心时间戳,而其他属性无关紧要,您可以使用以下严格的弱排序。你永远不会知道相同时间戳的对象会出现什么顺序:

bool operator< (const KeyT& key) const
{
    return timestamp < key.timestamp;
}

如果您需要订购我建议的所有属性boost::tie

bool operator< (const KeyT& key) const
{
    return boost::tie(timestamp, a, b, c, d, e) < boost::tie(key.timestamp, key.a, key.b, key.c, key.d, e.key);
}

【讨论】:

  • 第一个不起作用,因为如果 1
  • @Kim Sun-wu 通过说Now, I don't really care about the sorting on member vars a, b, c, d, e,您已经说过,就地图而言,这些对象相等的。您仍然可以使用operator== 来确认该对象与您期望的匹配。我可能只是误解了您的需求。您是否需要能够让map 直接找到给定键对象的精确匹配项以及主要按时间戳排序?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-03
  • 2014-07-22
  • 1970-01-01
  • 1970-01-01
  • 2018-09-05
相关资源
最近更新 更多