Search code examples
qtkeylookuplookup-tablesqhash

Implementing a QHash-like lookup with multiple keys


I'm trying to find the best way to implement a QHash-like lookup table that uses multiple keys to return one value. I have read that the Boost library has similar functionality, but I would like to avoid this if possible.

An example of what I would like to do is as follows (obviously the following pseudo-code is not possible):

//First key (int) - Engine cylinders
//Second key (int) - Car weight
//Value (int) - Top speed
MyLookup<int, int, int> m_Lookup
m_Lookup.insert(6, 1000, 210);
m_Lookup.insert(6, 1500, 190);
m_Lookup.value(6, 1000); //Returns 210

My first (and extremely slow) idea was to just create a Struct, and iterate over a list until I find a qualifying item.

Struct Vehicle {
   int cyl;
   int weight;
   int speed'
}

QList<Vehicle> carList; //Assume this is populated
for(i = 0; i < carList.length; ++i) { 
if(carList[i].cyl == 6 && carList[i].weight == 1000) {
return carList[i].speed; } }

My other idea was to concatenate the two keys into one key, and implement a couple functions to combine and separate the two keys when needed. While this would work, and probably be a lot faster than a full iteration, it seems a bit hacked together.

QHash<QString, int> m_Lookup;
m_Lookup.insert("6|1000", 210);

Does anyone know of a better way to try and achieve this?


Solution

  • Option 1

    Use a QPair as your key:

    QHash<QPair<int, int>, int> m_Lookup;
    
    m_Lookup.insert(QPair<int, int>(6, 1000), 210);
    m_Lookup.insert(QPair<int, int>(6, 1500), 190);
    
    qDebug("Value is %d", m_Lookup.value(QPair<int, int>(6, 1000)));
    

    Option 2

    Create a class to represent your desired vehicle characteristics (complete with equality/inequality operators) and create an implementation of qHash for your class:

    class Vehicle
    {
    public:
       Vehicle(short cylinders, short weight) 
          : m_Cylinders(cylinders), m_Weight(weight) { }
    
       short cylinders() const { return m_Cylinders; }
       short weight() const { return m_Weight; }
    
       bool operator==(const Vehicle& other) const 
          { return (m_Cylinders == other.m_Cylinders && m_Weight == other.m_Weight); }
       bool operator!=(const Vehicle& other) const 
          { return !operator==(other); }
    
    private:
       short m_Cylinders;
       short m_Weight;
    };
    
    inline uint qHash(const Vehicle& key)
    {
       uint k = static_cast<uint>(key.cylinders()) << 16 | static_cast<uint>(key.weight());
       return k;
    }
    
    int main(int argc, char** argv)
    {
       QHash<Vehicle, int> m_Lookup;
    
       m_Lookup.insert(Vehicle(6, 1000), 210);
       m_Lookup.insert(Vehicle(6, 1500), 190);
    
       qDebug("Value is %d", m_Lookup.value(Vehicle(6, 1000)));
    
       return 0;
    }