在Qt map容器中使用QSet作为键

时间:2014-03-07 05:16:08

标签: c++ qt

我需要一个映射,其中键是唯一的,每个键都是一个包含3个数据项的自定义POD结构。这些值只是指向对象实例的指针。

从阅读docs for Qt's QMap vs QHash开始,好像我在地图中使用QSet作为关键字,然后我应该使用QHash,因为QSet提供operator==()但不是{{1} }。这是一个公平的假设吗?但是,文档还说QHash需要一个名为qHash()的“全局qHash函数”,但我不清楚如何提供它,或者它是否是QSet的隐式部分?

如果我使用一个简单的结构作为我的密钥,我遇到了处理operator<()的相同问题,尽管一个简单的POD结构应隐式具有qHash()的可接受重载,它只是比较所有数据,对吗?

我对这里最好的方法有一些建议。

1 个答案:

答案 0 :(得分:2)

我建议使用QHash,除非您需要对键进行排序(我假设您没有)。

operator==函数已由QSet提供,假设由集合管理的类也定义了该运算符(所有基本数据类型和QString等都有这一点)。

  

如果两组包含相同的元素,则认为它们相等。

     

此函数需要值类型来实现operator ==()。

您仍然需要提供qHash()函数,该函数通常是这样定义的:

inline uint qHash( QSet<whatever> set )
{
    return /* calculate a hash based on all the elements. */
}

只要定义QHash的代码包含包含定义的文件,该定义就可以放在任何地方。如果您在此示例中为引用为whatever的内容设置了自己的类,则可以使用该定义,例如在你的班级定义背后。

请注意,qHash函数只需要确保等式obj1 == obj2的结果始终等于qHash(obj1) == qHash(obj2)的结果。

这意味着您不一定要生成唯一的哈希值,但文档中有以下注释:

  

但是,为了获得良好的性能,qHash()函数应该尝试尽可能为不同的键返回不同的哈希值。


示例:

我为一个存储字符串的集合编写了一个小测试应用程序:

#include <QtCore/QSet>
#include <QtCore/QHash>
#include <QtCore/QList>
#include <QtCore/QDebug>    

typedef QSet<QString> QStringSet;
typedef QHash< QStringSet, QObject* > QStringSetToObjectHash;

inline uint qHash( const QStringSet mySet )
{
    // convert the set to a list so we can sort and iterate over it
    QList<QString> mySetAsList = mySet.toList();
    qSort( mySetAsList );

    // take the hash of the first item
    uint result = qHash( mySetAsList.first() );

    // for each remaining element in the list
    for( int index = 1; index < mySetAsList.count(); index++ )
    {
        // XOR the current result with the hash of the next item
        result ^= qHash( mySetAsList.at( index ) );
    }

    return result;
}

void insertIntoHash( QStringSetToObjectHash& hash, const QStringSet& key, QObject* const value )
{
    qDebug() << "---------------------------------";
    qDebug() << "Element hash value:" << qHash( key );

    foreach( QStringSet existingKey, hash.keys() )
    {
        if( existingKey == key )
        {
            qDebug() << "Similar element found using == operator. QHash will not store that item twice";
        }
    }

    hash.insert( key, value );
    qDebug() << "QHash count:" << hash.count();
}

int main(int argc, char *argv[])
{
    QStringSetToObjectHash testHash;

    QObject dummy;

    QStringSet testSet;
    testSet.insert( "1" );
    testSet.insert( "12" );

    insertIntoHash( testHash, testSet, &dummy );

    QStringSet testSet2( testSet );

    insertIntoHash( testHash, testSet2, &dummy );

    QStringSet testSet3;
    testSet3.insert( "12" );
    testSet3.insert( "1" );

    insertIntoHash( testHash, testSet3, &dummy );

    QStringSet testSet4;
    testSet4.insert( "1" );
    testSet4.insert( "2" );
    testSet4.insert( "3" );

    insertIntoHash( testHash, testSet4, &dummy );
}

这会产生以下输出:

--------------------------------- 
Element hash value: 883
QHash count: 1 
---------------------------------
Element hash value: 883  Similar element found using == operator. QHash will not store that item twice
QHash count: 1 
---------------------------------
Element hash value: 883  Similar element found using == operator. QHash will not store that item twice
QHash count: 1 
--------------------------------- 
Element hash value: 48
QHash count: 2