Newsgroup: it.comp.lang.c++
Titolo: Come rappresentare una corrispondenza biunivoca (STL?)

Ciao, ho un problema di rappresentazione:
devo associare biunivocamente numeri interi e stringhe, in modo che,
data ad esempio la seguente associazione
5 <--> "Bianca"
2 <--> "Bernie"
6 <--> "Evinrude"
Io possa risalire dal numero alla stringa corrispondente *e
viceversa*. Es.: CorrStringa(5) dà "Bianca", e CorrNum("Bernie") dà 2.
Un modo potrebbe essere quello di costruire due map di STL, una
(CorrNum) con key string e data int e l'altra viceversa (CorrString)
key int e data string. Il problema è che bisogna tenerle allineate
(due inserimenti e due cancellazioni per ogni elemento), e cmq non mi
sembra il max dell'eleganza, però l'accesso è immediato.
Avete delle alternative?
Grazie mille, giulio
Per favore togliete "!RemoveMe!" dall'indirizzo per rispondere via email
Please remove "!RemoveMe!" from the address to email me

 sembra il max dell'eleganza, però l'accesso è immediato.
Incapsula le due corrispondenze in una classe; il problema di
tenerle allineate lo risolverai cosi` una volta per tutte nei
metodi della classe-capsula.  Internamente, la classe-capsula
puo` usare strategie arbitrarie di implementazione (ad esempio,
se hai sotto mano un database relazionale, una tabella con
due colonne e due indici; all'altro estremo, per pochi elementi,
un semplice vettore di coppie da cercare linearmente) senza
cambiare l'interfaccia che offre a tutto il resto del tuo codice.
Per dimensioni intermedie, la strategia implementativa piu`
adeguata potrebbe essere composta da due mappe ognuna
delle quali usi come valori delle coppie dato-vero/iteratore
nell'altra mappa -- questo accelera le operazioni, pero` a
prezzo di complicazione e riferimenti incrociati; bisogna
sperimentare varie strategie implementative per valutarne
le prestazioni nei tuoi problemi reali.  Ma l'interfaccia che
questo componente presentera` al resto del tuo codice e`
piu` importante -- l'implementazione e` + facile da
modificare.
Alex

 viceversa*. Es.: CorrStringa(5) dà "Bianca", e CorrNum("Bernie") dà 2.
Ad occhio, quello che ti serve e' di rappresentare i tuoi dati con un
pair<int, string>; l'insieme dei dati puo' trovar posto in un dynamic
array, quindi un vector (o una deque) di pair<int, string>.
Mantieni poi due map (o multimap), una di corrispondenza (interi) <->
(indice nel vettore) ed una di corrispondenza (string) <-> (indice nel
vettore).
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

... anzi, visto che ho un attimo di tempo, ecco un esempio
funzionante; ti manca solo di incapsulare tutto in una classe.
MLO@axcdf4 3 $ cat foo.cxx
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
typedef pair<int, string>                pIS;
typedef vector<pIS>                      vIS;
typedef map<int, vIS::const_iterator>    mIP;
typedef map<string, vIS::const_iterator> mSP;
void add(
  const int    i,
  const string s,
  vIS *        pv,
  mIP *        pi,
  mSP *        ps
) {
  vIS::const_iterator it = pv->insert(pv->end(), make_pair(i, s));
  // No error checking for duplicate keywords
  pi->insert( make_pair(i, it) );
  ps->insert( make_pair(s, it) );
}
int main()
{
  vIS v;
  mIP m1;
  mSP m2;
  add(5, "Bianca",   &v, &m1, &m2);
  add(2, "Bernie",   &v, &m1, &m2);
  add(6, "Evinrude", &v, &m1, &m2);
  // No error checking for missing keywords
  vIS::const_iterator it = (m1.find(5))->second;
  cout << "5 --> " << it->second << endl;
  it = (m2.find("Bernie"))->second;
  cout << "Bernie --> " << it->first << endl;
}
MLO@axcdf4 4 $ KCC -o foo foo.cxx
MLO@axcdf4 5 $ ./foo
5 --> Bianca
Bernie --> 2
