std::map, custom key type with sorting only on one variable

萝らか妹 提交于 2020-01-15 11:18:30

问题


I have a key type:

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;
    }
};

Now, I don't really care about the sorting on member vars a, b, c, d, e, the only thing I want to ensure is that the map is sorted on timestamp. I also just realized that if I have two instances of KeyT one, two, where everything is the same except for "d", then both one < two, and two < one would be false. The only way to fix that is to write comparisons for all possible combinations of all member variables.. I'm fairly certain I'm missing something obvious, so what's the best solution in this case?

Thanks!


回答1:


I think this does what you need:

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;
}

This is a sensible if ugly pattern to use whenever you have a prioritised list of variables you want to sort on within a comparable class.




回答2:


First, you should compare only the next current key that has not been compared for being less than, and drop the else after return, like this:

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 you need to compare only the timestamp, leave the first if, and delete the remaining ones:

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

When you use this operator for comparing your keys, the items with identical timestamp will not be reordered.




回答3:


If all you care about is the timestamp, and the other attributes just don't matter, you can use the following which is a strict weak ordering. You'll just never know what order the objects of the same timestamp will appear:

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

If you need to order on all the attributes I suggest 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);
}


来源:https://stackoverflow.com/questions/11317538/stdmap-custom-key-type-with-sorting-only-on-one-variable

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!