在Qt映射容器中使用QSet作为键 [英] Using a QSet as a key in Qt map container

查看:445
本文介绍了在Qt映射容器中使用QSet作为键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need a map where the keys will be unique, and each key will be a set or a custom POD struct which contains 3 data items. The values are simply pointers to object instances.

从读取 docs for Qt的QMap vs QHash ,似乎如果我使用 QSet 作为我的地图中的键,然后我应该使用QHash,因为QSet提供运算符==()但不是 operator<()。这是一个公平的假设吗?然而,文档还说,QHash需要一个全局qHash函数,称为qHash(),但是我不清楚如何提供,或者如果它是QSet的隐式部分?

From reading the docs for Qt's QMap vs QHash, it appears as though if I use QSet as the key in my map, then I should use QHash since QSet provides operator==() but not operator<(). Is this a fair assumption? However, the docs also say that QHash requires a "global qHash function called qHash()", but it is not clear to me how this is provided, or if it is an implicit part of QSet?

如果我使用一个简单的结构作为我的键,我遇到了处理 qHash()的同一个问题,虽然一个简单的POD结构应该隐含有运算符==()的可接受的重载,只是比较所有数据,是否正确?

If alternatively I use a simple struct as my key, I run into the same issue of dealing with qHash(), though a simple POD struct should implicitly have an acceptable overload of operator==() that simply compares all the data, correct?

推荐答案

我建议使用 QHash

I advise using QHash unless you need to sort your keys (which I assume you don't).

运算符== 函数已经由 QSet 提供,假设由集合管理的类具有该操作符定义(所有基本数据类型和

The operator== function is already provided by QSet, assuming the class which is managed by the set has that operator defined as well (all of the basic data types and QString etc have that).


如果两个集合包含相同的元素,则两个集合被认为是相等的。

Two sets are considered equal if they contain the same elements.

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

This function requires the value type to implement operator==().

仍然需要提供 qHash()函数,其通常定义如下:

You still need to provide the qHash() function which is usally defined like this:

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

这个定义真的可以放在任何地方,定义 QHash 包括包含定义的文件。如果你在这个例子中有一个自己的类作为 whatever 的引用,你会把这个定义。

This definition can really be placed anywhere, as long as the code which defines the QHash includes the file which contains the definition. If you have an own class for what is referenced as whatever in this example, you would put that definition e.g. behind your class definition.

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

Note that the qHash function only needs to ensure that the result of the equation obj1 == obj2 is always equal to the result of qHash(obj1) == qHash(obj2).

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

This means you don't necessarily have to produce unique hashes, but there is the following note in the documentation:


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

However, to obtain good performance, the qHash() function should attempt to return different hash values for different keys to the largest extent possible.






示例:



p>


Examples:

I wrote a small test application for a set which stores strings:

#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

这篇关于在Qt映射容器中使用QSet作为键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆