Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concise lists/vectors in C++

I'm currently translating an algorithm in Python to C++.

This line EXCH_SYMBOL_SETS = [["i", "1", "l"], ["s", "5"], ["b", "8"], ["m", "n"]] is now

    vector<vector<char>> exch_symbols;

    vector<char> vector_1il;
    vector_1il.push_back('1');
    vector_1il.push_back('i');
    vector_1il.push_back('l');

    vector<char> vector_5s;
    vector_5s.push_back('5');
    vector_5s.push_back('s');

    vector<char> vector_8b;
    vector_8b.push_back('8');
    vector_8b.push_back('b');

    vector<char> vector_mn;
    vector_mn.push_back('m');
    vector_mn.push_back('n');

    exch_symbols.push_back(vector_1il);
    exch_symbols.push_back(vector_5s);
    exch_symbols.push_back(vector_8b);
    exch_symbols.push_back(vector_mn);

I hate to have an intermediate named variable for each inner variable in a 2-D vector. I'm not really familiar with multidimensional datastructures in C++. Is there a better way?

What's happening afterwards is this:

multimap<char, char> exch_symbol_map;

/*# Insert all possibilities
    for symbol_set in EXCH_SYMBOL_SETS:
        for symbol in symbol_set:
            for symbol2 in symbol_set:
                if symbol != symbol2:
                    exch_symbol_map[symbol].add(symbol2)*/
void insert_all_exch_pairs(const vector<vector<char>>& exch_symbols) {
    for (vector<vector<char>>::const_iterator symsets_it = exch_symbols.begin();
        symsets_it != exch_symbols.end(); ++symsets_it) {
            for (vector<char>::const_iterator sym1_it = symsets_it->begin();
                sym1_it != symsets_it->end(); ++sym1_it) {
                    for (vector<char>::const_iterator sym2_it = symsets_it->begin();
                        sym2_it != symsets_it->end(); ++sym2_it) {
                            if (sym1_it != sym2_it) {
                                exch_symbol_map.insert(pair<char, char>(*sym1_it, *sym2_it));
                            }
                    }
            }
    }
}

So this algorithm should work in one way or another with the representation here. The goal is that EXCH_SYMBOL_SETS can be easily changed later to include new groups of chars or add new letters to existing groups. Thank you!

like image 244
Felix Dombek Avatar asked Dec 07 '25 09:12

Felix Dombek


2 Answers

I would refactor, instead of vector<char>, use std::string as internal, i.e.

vector<string> exch_symbols;
exch_symbols.push_back("1il");
exch_symbols.push_back("s5");
exch_symbols.push_back("b8");
exch_symbols.push_back("mn");

then change your insert method:

void insert_all_exch_pairs(const vector<string>& exch_symbols) 
{
  for (vector<string>::const_iterator symsets_it = exch_symbols.begin(); symsets_it != exch_symbols.end(); ++symsets_it) 
  {
    for (string::const_iterator sym1_it = symsets_it->begin();  sym1_it != symsets_it->end(); ++sym1_it) 
    {
      for (string::const_iterator sym2_it = symsets_it->begin(); sym2_it != symsets_it->end(); ++sym2_it) 
      {
        if (sym1_it != sym2_it)
          exch_symbol_map.insert(pair<char, char>(*sym1_it, *sym2_it));
      }
    }
  }
}
like image 150
Nim Avatar answered Dec 09 '25 23:12

Nim


You could shorten it by getting rid of the intermediate values

vector<vector<char> > exch_symbols(4, vector<char>()); //>> is not valid in C++98 btw.
//exch_symbols[0].reserve(3)
exch_symbols[0].push_back('i');
etc.

You could also use boost.assign or something similiar
EXCH_SYMBOL_SETS = [["i", "1", "l"], ["s", "5"], ["b", "8"], ["m", "n"]] then becomes vector<vector<char>> exch_symbols(list_of(vector<char>(list_of('i')('1')('l')))(vector<char>(list_of('s')('5'))(list_of('m')('n'))) (not tested and never used it with nested vectors, but it should be something like this)

like image 45
DaVinci Avatar answered Dec 09 '25 22:12

DaVinci