Частичное соответствие ключа QHash

У меня есть QHash, определенный следующим образом

QHash<QString, QString> hashLookup;

Я вставил несколько значений в этот хэш следующим образом:

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

У меня есть несколько QStrings следующим образом:

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

Я должен найти, существуют ли эти значения в hashLookup, то есть, поскольку OMG_1 содержит OMG, я должен получить Oh my God!.

Я пытался сделать это с помощью

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

который, конечно, пытается найти ключ OMG, которого нет в таблице поиска, и ничего не возвращает. Возможно ли частичное совпадение значений ключей в Qt? Если да, то как мне это реализовать.


person smyslov    schedule 10.06.2016    source источник
comment
Ваш вариант использования принимает только ‹word_in_hash›_‹random_prefix›? Если это так, вы можете просто разделить его на _ и взять первую часть.   -  person JefGli    schedule 10.06.2016
comment
не используйте QHash для такой цели. Это неправильная структура данных. Функция qHash определена глобально для строк и qHash("OMG") != qHash("OMG_1"). Вы хотите использовать QMap, std::map с компаратором, подобным тому, что предложил Кирилл Черников.   -  person UmNyobe    schedule 10.06.2016
comment
Некоторые также в форме ‹word_in_hash›‹random_prefix›, т. е. без _, как OMG1, RIP2A и т. д. Я уже думал о вашем предложении, но поскольку оно не решает сценарий OMG1, RIP2A и т. д., я не был уверен, как действовать @JeffreyvandeGlind   -  person smyslov    schedule 10.06.2016


Ответы (2)


В классе QHash нет возможности извлекать значения путем частичного совпадения ключа, поскольку QHash использует хеш-функцию (документация Qt: qHash), который:

Функция qHash() вычисляет числовое значение на основе ключа. Он может использовать любой мыслимый алгоритм, если он всегда возвращает одно и то же значение при задании одного и того же аргумента. Другими словами, если e1 == e2, то также должно выполняться qHash(e1) == qHash(e2). Однако, чтобы получить хорошую производительность, функция qHash() должна пытаться возвращать разные хеш-значения для разных ключей в максимально возможной степени.

Разные ключи почти всегда дают разный хеш.

В своей задаче вы можете запустить QHash ключей и провести сравнение с QString функциональностью. Что-то вроде этого:

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);
person Kirill Chernikov    schedule 10.06.2016
comment
Поскольку с QHash немного сложно, не могли бы вы предложить использовать что-то еще, кроме QHash, но которое служит той же цели. - person smyslov; 10.06.2016
comment
В Qt нет контейнерного класса, который позволял бы вам извлекать значения путем частичного сопоставления ключа. Вот почему вы будете вынуждены использовать такие трюки с этой задачей. - person Kirill Chernikov; 10.06.2016

Во-первых, в вашем примере метод QHash.contains(QString key) пытается найти OMG_1, но на самом деле не находит.

Вы можете реализовать метод, который берет расширенный ключ и пытается найти в хэше любой подраздел данного значения. Здесь вы должны определить некоторые правила, я думаю, иначе он может не вернуть предполагаемое значение.

Рассмотрим следующий пример: хэш содержит ключи OMG и OM. Чтобы соответствовать предоставленному расширенному ключу, вы реализуете что-то вроде этого

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

Этот метод позволит вам найти ключ OMG, но не OM, который содержится в этом ключе. Вы также можете реализовать метод, который будет принимать первый символ предоставленного расширенного ключа и проверять его на включение. Если не найдется, возьмет второй и снова проверит и так далее. Это заменит OM на OMG.


Также имейте в виду, что позже вы можете работать с совпадающим ключом, и поэтому вам следует вернуть его, а не просто возвращать true.

person maxik    schedule 10.06.2016