55502f40dc8b7c769880b10874abc9d0

looking for stability and speed, is this the right route to take?
the idea is to be able to do myary[row]["column-heading"] = 77;

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


template <class Tk>
class head
{
  private:
   map<Tk, unsigned int> m_head;
  public:
   //optionally use another map to define the column indeces
   head(map<Tk, unsigned int>& column_defs)
     : m_head(column_defs){ }
   
   //define the columns based on the data in this vector  
   head(const vector<Tk>* pvct_columns = NULL)
   {
      if (pvct_columns != NULL){
         for (unsigned int i = 0; i < pvct_columns->size(); ++i)
         {
            m_head[ (*pvct_columns)[i] ] = i;
         }                
      }                
   }   
  
   bool exists(const Tk& col){
      return m_head.find(col) != m_head.end();
   }
   
   /**
    * Get the value if it exists,
    * Useful if we do not know the column headers associated with this
    * associative array
    *
    * @param i the index 
    * @return pointer to the Tk column it found, NULL if does not exist
    */
   const Tk* value_to_key(unsigned int i)
   {
     bool found = false;
     map<Tk, unsigned int>::iterator it = m_head.begin(); // internalMap is std::map
     while(it != m_head.end())
     {
        found = (it->second == i);
        if(found)
                return &it->first;
        ++it;
     }
     return NULL;    
   }
   
     
   void undefine(const Tk& col){
         m_head.erase(m_head.find(col));
   }
   unsigned int count(){ return m_head.size(); }
   inline unsigned int size(){ return m_head.size(); }
   //return the column index
   unsigned int& column(const Tk& col){ return m_head[col]; }
   
   unsigned int& operator[](const Tk& col){ return m_head[col]; }
   
   const Tk& operator[](unsigned int i)
   {
      const Tk* pstr = value_to_key(i);
      if (pstr == NULL){ throw 1; }
      return (*pstr);
   }
};

template <class Tk, class Tv>
class row
{
   head<Tk>* m_phead;
   vector< vector<Tv> >* m_pvdata; ///pointer to the full data array
  public:
   unsigned int m_row;
  public:
    explicit row(head<Tk>* phead, vector< vector<Tv> >* pvdata, unsigned int row_index = 0)
       : m_phead(phead), m_pvdata(pvdata), m_row(row_index)
    { }
  //this is the second bracket[row][key]
  Tv& operator[](const Tk& key) const
  {
     return (*this)[ m_phead->column(key) ];  
  } 
  
  //this is the second bracket[row][index]
  Tv& operator[](unsigned int index) const
  {
     return (*m_pvdata)[m_row][index];  
  }

  vector <Tv>& operator=(std::vector<Tv>& rhs)
  {
     if (rhs.size() > m_phead->size())
     {
         throw Tk( "vector has more entries than columns" );
     }
     else
     {
        (*m_pvdata)[m_row] = rhs;
     }
     return (*m_pvdata)[m_row];
  }

  vector <Tv>& operator=(const std::vector<Tv>& rhs) const
  {
     if (rhs.size() > m_phead->size())
     {
         throw Tk( "vector has more entries than columns" );
     }
     else
     {
        (*m_pvdata)[m_row] = rhs;
     }
     return (*m_pvdata)[m_row];
  }
};

/**
 * This contains the core data, the vector of all the rows, 
 * and the column header information 
 */
template <class Tk, class Tv>
class assoc_array
{
  private:
    vector< vector<Tv> > m_data;
    head<Tk> m_head;
    row<Tk,Tv> m_temp_row;
    
  public:
    assoc_array(unsigned int num_rows = 0, const vector<Tk>& vct_columns = vector<Tk>(1), int fill_value = 0)
    : m_data(num_rows, vector<Tv>(vct_columns.size(), fill_value)), m_head(&vct_columns), m_temp_row(&m_head, &m_data)
    {
    }
    
    
    const Tk& get_column(unsigned int i){ return m_head[i]; }
    const int numCols(){ return m_head.size(); }
    
    
    void define_column(const Tk& col, unsigned int index){
       m_head[col] = index;
    }
    void undefine_column(const Tk& col){ 
       m_head.undefine(col);
    }
    
  //access either using a column name or column index -- optimized (not 2 different entries like PHP)
    Tv& data(unsigned int row, unsigned int col){ return m_data[row][col]; }
    Tv& data(unsigned int row, const Tk& scol){
          Tv col = m_head.column(scol); 
          return m_data[row][col]; 
    }
    
    const int numRows(){ return m_data.size(); }
    inline const int count(){ return numRows(); }
    
    
    
    const row<Tk, Tv>& operator[](unsigned int row)
    {
      //set the temporary row index so the next time 
      m_temp_row.m_row = row;
      return m_temp_row; 
    }
};


#include <iostream>

char* rword (char *word)
{
  int len = rand () % 6 + 1;
  word [len] = 0;
  while (len) word [--len] = 'a' + rand () % 26;
  return word;
}

template<class Tk, class Tv>
void print(assoc_array<Tk, Tv>& ary)
{
   for (int j = 0; j < ary.numCols(); j++)
   {
     cout << ary.get_column(j) << "\t";
   }
   cout << endl;
   for (int j = 0; j < 40; ++j){ cout << "-"; }
   cout << endl;

   for (int i = 0; i < ary.numRows(); ++i)
   {
      for (int j = 0; j < ary.numCols(); j++)
      {
         cout << ary[i][j] << "\t";
      }
      cout << endl;
   }
}




int main()
{
   assoc_array<string, int> ary;
   
   vector<string> cols(5);
   cols[0] = "text";
   cols[1] = "book";
   cols[2] = "chapter";
   cols[3] = "verse";
   cols[4] = "rowid";
   assoc_array<string, int> big_ary(5, cols, 8888);
   //set some data
   big_ary.data(2, "rowid") = 2;
   big_ary.data(2, "chapter") = 15;
   
   for (int i = 0; i < big_ary.numRows(); ++i)
   {
     std::vector<int> vct(big_ary.numCols(), i);
     big_ary[i] = vct;
   }
   

   
   print(big_ary);
   
   system("PAUSE");
   
   

}

/** output **
text    book    chapter verse   rowid
----------------------------------------
0       0       0       0       0
1       1       1       1       1
2       2       2       2       2
3       3       3       3       3
4       4       4       4       4
**/

Refactorings

No refactoring yet !

A7a13a4a7f8141b250fe5264509a36ed

raul

March 12, 2010, March 12, 2010 13:27, permalink

No rating. Login to rate!

Use std::map for this:

#include <map>
#include <string>
#include <iostream>
void foo()
{
   std::map<string,int> myArray;
   myArray["slot_0"] = 1;
   myArray["slot_1"] = 2;
   myArray["slot_2"] = 3;

   cout << myArray["slot_0"] << " " << myArray["slot_1"] << " " << myArray["slot_2"];
}

Your refactoring





Format Copy from initial code

or Cancel