1

I have a QHash defined as follows

QHash<QString, QString> hashLookup;

I have inserted a few values to this hash as follows:

hashLookup.insert("OMG", "Oh my God!");
hashLookup.insert("LOL", "Laugh out loud");
hashLookup.insert("RIP", "Rest in peace");
// and so on

I have a few QStrings as follows:

QString a = "OMG_1";
QString b = "LOL_A";
QStirng c = "OMG_YOU";
QString d = "RIP_two";

I am supposed to find if these values exist in hashLookup, i.e, since OMG_1 contains OMG, I should be able to retrieve Oh my God!.

I have tried to do this using

if(hashLookup.contains(a)
//do something

which ofcourse tries to look for a key OMG which is not present in the lookup table and does not return anything. Is partial matching of key values possible in Qt? If yes, how should I go about implementing this.

smyslov
  • 1,279
  • 1
  • 8
  • 29
  • Does your use-case only accept _? If so, you can just split it on the _ and take the first part. – JefGli Jun 10 '16 at 07:13
  • **do not use QHash** for such a purpose. It is the wrong data structure. The function qHash is defined globally for strings, and `qHash("OMG") != qHash("OMG_1")`. You want to use a QMap, std::map with a comparator similar to what Kirill Chernikov proposed. – UmNyobe Jun 10 '16 at 07:51
  • Some are also in the form of , i.e., without the _ like OMG1, RIP2A etc. I've already thought about your suggestion, but since it doesn't solve the scenario OMG1, RIP2A etc., I was not sure how to proceed @JeffreyvandeGlind – smyslov Jun 10 '16 at 07:51

2 Answers2

2

There is no opportunity in QHash class to extract values by partial matching of key, because QHash use hash function (Qt documentation: qHash) which:

The qHash() function computes a numeric value based on a key. It can use any algorithm imaginable, as long as it always returns the same value if given the same argument. In other words, if e1 == e2, then qHash(e1) == qHash(e2) must hold as well. However, to obtain good performance, the qHash() function should attempt to return different hash values for different keys to the largest extent possible.

Different keys give almost always different hash.

In your task you can run on QHash keys and make comparison with QString functionality. Something like this:

QString getHashValue(const QString& strKey, const QHash<QString, QString>& hashLookup)
{
    QList<QString> uniqueKeys = hashLookup.uniqueKeys();
    foreach(const QString& key, uniqueKeys)
    {
        if(strKey.contains(key))
            return hashLookup.value(key);
    }
}

...

getHashValue("OMG_1", hashLookup);
Kirill Chernikov
  • 1,387
  • 8
  • 21
  • 1
    Since it is a little tricky with QHash, would you suggest using something else other than QHash but which serves the same purpose. – smyslov Jun 10 '16 at 07:38
  • There is no container class in Qt which let you to extract values by partial matching of key. That's why you will be forced to use such tricks with this task. – Kirill Chernikov Jun 10 '16 at 07:59
1

First, in your example the QHash.contains(QString key) method tries to find OMG_1, which in fact it will not find.

You may implement a method which will take a expanded key and tries to locate any subkey of the given value in the hash. Here you have to define some rules I think or it may not return the intendend value.

Think of following example: the hash contains the keys OMG and OM. To match the provided expanded key you implement something like this

bool hashContainsExpanded(const QString &key) const {
    if (!hash.contains(key) && key.length() > 1)
        return hasContainsExpanded(key.substring(0, key.length() - 1));
    return hash.contains(key);
}

This method will let you find the key OMG but not OM which is contained in this key. You may also implement a method which will take the first character of the provided expanded key and test it for containment. If not found, it will take the second and test again and so on. This will match OM in favour of OMG.


Also keep in mind, that you may work later with the matched key and thus you should return it instead of only returning true.

maxik
  • 1,053
  • 13
  • 34