Phil-ZXX
Phil-ZXX

Reputation: 3285

Table Representation in C++

Basically, say, I have the following data:

enter image description here

(let me note that the columns change with every piece of data I get, i.e. I need to keep things general and cannot restrict my solution to only Tenor, Date, etc.)

Now I want to be able to represent and conveniently access this data in an object/class in C++.

I have been playing around with map a bit:

#include <iostream>
#include <map>
#include <string>
using namespace std;

class my_table {
private:
    map<string, map<string, string>> c;

public:
    void set(string key1, string key2, string value){ this->c[key1][key2] = value; }

    string get(string key1, string key2){
        map<string, map<string, string>>::iterator it = this->c.find(key1);
        if (it != this->c.end()){
            map<string, string>::iterator it2 = this->c[key1].find(key2);
            if (it2 != this->c[key1].end()){
                return c[key1][key2];
            }
            return "n/a";
        }
        return "n/a";
    }
};

void main() {
    my_table a;
    a.set("1", "Tenor", "1D");
    cout << a.get("1", "Tenor") << endl; // returns '1D'
    cout << a.get("2", "Tenor") << endl; // returns 'n/a'
    cout << a.get("1", "Rate") << endl;  // returns 'n/a'
}

But I am not overly satisfied with this implemenation. In particular, I would want to be able to do things like:

a.get("Tenor","3M", "Rate")                   // should return '1.6%'
a.get("Date","01-Jan-2016", "Responsibility") // should return 'MG'
a.get_all("Type","Forward", "Rate")           // should return an array {1.3%,2.4%}
a.get_row(4)                                  // should return an array {4M,...,2.0%,MG}


And:

Upvotes: 2

Views: 12487

Answers (3)

Dave the Sax
Dave the Sax

Reputation: 328

Limiting yourself to maps could overcomplicate this somewhat. If I understand this correctly, the data structure is completely undefined at compile time. In that case perhaps a simpler way to implement it is as a vector of hash-key-value triples, like this:

#include "stdafx.h"
#include <string>
#include <vector>
#include <iostream>

using namespace std;

class HashKeyValue
{
private:
    string hash;
    string key;
    string value;

public:
    HashKeyValue() {}
    HashKeyValue(string h, string k, string v)
    {
        hash = h;
        key = k;
        value = v;
    }
    string getHash()  { return hash;  }
    string getKey()   { return key;   }
    string getValue() { return value; }
};

class my_table
{
private:
    vector<HashKeyValue> hkv;

public:
    my_table() {}
    void set(string h, string k, string v)
    {
        hkv.push_back(HashKeyValue(h, k, v));
    }
    string getV(string h, string k)
    {
        for (unsigned int i = 0; i < hkv.size(); i++)
        {
            if (hkv[i].getHash() == h && hkv[i].getKey() == k)
                return hkv[i].getValue();
        }
        return "n/a";
    }
    string getByColValue(string col1, string val, string col2)
    {
        string hash;
        int got = 0;
        for (unsigned int i = 0; i < hkv.size() && !got; i++)
        {
            if (hkv[i].getKey() == col1 && hkv[i].getValue() == val)
            {
                hash = hkv[i].getHash();
                got = 1;
            }
        }
        if (got)
        {
            for (unsigned int i = 0; i < hkv.size(); i++)
            {
                if (hkv[i].getHash() == hash && hkv[i].getKey() == col2)
                    return hkv[i].getValue();
            }
            return "n/a";
        }
        else return "n/a";
    }
};


int main()
{
    my_table m;
    m.set("1", "Tenor", "1D");
    m.set("3", "Tenor", "3M");
    m.set("3", "Rate", "1.6%");
    cout << "get-1-Tenor(1D): " << m.getV("1", "Tenor") << endl;
    cout << "get-1-Alto(n/a): " << m.getV("1", "Alto") << endl;
    cout << "get-3-Rate(1.6%): " << m.getV("3", "Rate") << endl;
    cout << "getBCV-Tenor-3M-Rate(1.6%): " << m.getByColValue("Tenor", "3M", "Rate") << endl;
    return 0;
}

Hopefully getByColValue() makes sense; it first looks up the hash, then looks up the Rate for that hash. The hash is what relates each key-value pair to others on the same row. It shouldn't be too tricky to change getByColValue() to return a vector<string> instead, for the getByColValue("Type","Forward","Rate") case: just make hash a vector<string> instead, define the return type as another vector<string>, and a few other tweaks.

This also makes the implementation of getRow() fairly trivial; just loop over hkv where hash==rowid and bung the key/value pairs (or just the values) into a vector.

Upvotes: 1

Furkan Fidan
Furkan Fidan

Reputation: 121

How about the matrix type from boost.ublas? You can create a simple enum type to easily reference columns.

For querying you can probably build something quick via the filter_iterator.

Hope this helps!

Edit: Sorry didn't notice your comment. A quick hack I can think of to support dynamic column size is using a hash map for storing column name to column index mapping in a separate hash map. Good luck!

Upvotes: 1

Arne
Arne

Reputation: 8509

enum struct Type {
  Spot
  Forward
}


struct Row {
  string tenor;
  Date date;
  int convention;
  Type type;
  double rate;
  ResposibilityType responsibility;
};

std::vector<Row> table = {
  [...]
}

access you do with std::find_if. Tables in databases might be stored like this internally. If you want multiple primary keys you can create for each key a map that maps from the primary key to an element in table. If you want a combined key, you need tuple like this std::map<std::pair<Key1,Key2>, Row*>

Upvotes: 3

Related Questions