OVH Cloud OVH Cloud

Tableau associatif à plusieurs dimensions

12 réponses
Avatar
Adrien Constant
Bonjour,

De la FAQ C++ lite:

[34.2] How can I make a perl-like associative array in C++?
Use the standard class template std::map<Key,Val>:

#include <string>
#include <map>
#include <iostream>

int main()
{
std::map<std::string, int, std::less<std::string> > age;
age["Fred"] = 42; // Fred is 42 years old
std::cout << "Fred is " << age["Fred"] << " years old\n";
}

Seulement,map n'associe que key à val et ne permet pas d'utiliser
plusieurs dimensions.

Y a t-il une fonction de librarie standard qui permette de faire du genre
age["Europe"]["France"]["Fred"] = 42;
par exemple ?

Sachant que le nombre de niveaux maximum n'est connu qu'à l'exécution.

Merci.

10 réponses

1 2
Avatar
Christophe de Vienne
Adrien Constant wrote:

Y a t-il une fonction de librarie standard qui permette de faire du genre
age["Europe"]["France"]["Fred"] = 42;
par exemple ?


Il suffit de faire des maps ( de maps )+ :

exemple avec 2 niveaux :
std::map< std::string, std::map< std::string, int > > age;
age["xxx"]["yyy"] = ABSOLUTE;



Sachant que le nombre de niveaux maximum n'est connu qu'à l'exécution.


Comment peux-tu écrire age["Europe"]["France"]["Fred"] = 42 si tu ne connais
pas le nombre de niveaux à l'écriture du code ?



Merci.


De rien

A+

Christophe

Avatar
Vincent Richard

age["Fred"] = 42; // Fred is 42 years old


Encore un 42 ? :-)

Vincent

--
vmime, une bibliothèque C++ sous licence GPL pour parser et générer
des messages au format MIME : http://www.sourceforge.net/projects/vmime/

Avatar
Fabien LE LEZ
On Fri, 17 Oct 2003 15:05:49 +0200, Christophe de Vienne
wrote:

Il suffit de faire des maps ( de maps )+ :

exemple avec 2 niveaux :
std::map< std::string, std::map< std::string, int > > age;


Et typedef est ton ami, sinon ça devient vite ingérable (d'ailleurs je
ne déclare quasiment jamais de variables de type map, je fais un
typedef et je déclare une variable de ce type).

--
http://www.giromini.org/usenet-fr/repondre.html

Avatar
Fabien SK
Adrien Constant wrote:

Y a t-il une fonction de librarie standard qui permette de faire du genre
age["Europe"]["France"]["Fred"] = 42;
par exemple ?


Si tu as toujours trois clefs, tu peux faire une clef composée, un peu
comme:

class Clef
{
public:
Clef(std::string continent, std::string pays):m_Continent(continent),
m_Pays(pays){}

bool operator<(const Clef &autre)
{
if (m_Continent<autre.m_Continent)
return true;
if (m_Continent>autre.m_Continent)
return false;
if (m_Pays<autre.m_Pays)
return true;
if (m_Pays>autre.m_Pays)
return false;
return m_Nom<autre.m_Nom;
}
private:
std::string m_Continent;
std::string m_Pays;
std::string m_Nom;
};

Avatar
Fabien SK
Fabien SK wrote:

Adrien Constant wrote:

Y a t-il une fonction de librarie standard qui permette de faire du genre
age["Europe"]["France"]["Fred"] = 42;
par exemple ?



Si tu as toujours trois clefs, tu peux faire une clef composée, un peu
comme:
class Clef
[...]


Bon, il manque un "const" et une initialisation de paramètre, mais
l'idée est là.


Avatar
Christophe de Vienne
Fabien LE LEZ wrote:

On Fri, 17 Oct 2003 15:05:49 +0200, Christophe de Vienne
wrote:

Il suffit de faire des maps ( de maps )+ :

exemple avec 2 niveaux :
std::map< std::string, std::map< std::string, int > > age;


Et typedef est ton ami, sinon ça devient vite ingérable (d'ailleurs je
ne déclare quasiment jamais de variables de type map, je fais un
typedef et je déclare une variable de ce type).



C'est juste.


Avatar
Fabien LE LEZ
On Fri, 17 Oct 2003 19:18:25 +0200, Christophe de Vienne
wrote:

Fabien LE LEZ wrote:
[snip]


C'est juste.


Oh, un mitou ! ;-)

--
http://www.giromini.org/usenet-fr/repondre.html

Avatar
Christophe de Vienne
Fabien LE LEZ wrote:

On Fri, 17 Oct 2003 19:18:25 +0200, Christophe de Vienne
wrote:

Fabien LE LEZ wrote:
[snip]


C'est juste.


Oh, un mitou ! ;-)



AOL


Avatar
Vincent Lascaux
Seulement,map n'associe que key à val et ne permet pas d'utiliser
plusieurs dimensions.

Y a t-il une fonction de librarie standard qui permette de faire du genre
age["Europe"]["France"]["Fred"] = 42;
par exemple ?

Sachant que le nombre de niveaux maximum n'est connu qu'à l'exécution.


template<class T>
class lexicographical_container_compare : public <T, T, bool>
{
public:
bool operator () (const T& c1, const T& c2) const
{
return std::lexicographical_compare(c1.begin(), c1.end(), c2.begin(),
c2.end());
}
};

template<class Key, class Val>
class multidimensional_map :
public std::map<
std::vector<Key>,
Val,
lexicographical_container_compare< std::vector<Key> >
{};


multidimensional_map<string, int> age;
std::vector<std::string> Infos(3);
Infos[0] = "Europe"; Infos[1]="France"; Infos[2]="Fred";
age[Infos] = 42;

Bon, il faudrait encore creuser un peu pour rendre l'utilisation aussi
simple qu'en perl :-)
--
Vincent

Avatar
Fabien LE LEZ
On Fri, 17 Oct 2003 14:56:13 +0200, Adrien Constant
wrote:

Sachant que le nombre de niveaux maximum n'est connu qu'à l'exécution.


J'avais pas lu ça...
Bon, ben dans ce cas, la syntaxe que tu demandes me paraît difficile à
obtenir.

La solution qui me paraît la plus simple : un map<> avec comme clef
soit un vector<string>, soit une classe plus ou moins basée sur
vector<string>.

Autre solution : une structure d'arbre.

template <class Feuille> class Noeud
{
public:
typedef std::map <std::string, Noeud> Data;
bool EstFeuille() const;
class MauvaisType;
operator Feuille&() throw (MauvaisType);
Noeud& operator[] (std::string const&) throw (MauvaisType);

private:
Feuille valeur;
Data noeuds_enfants;
};

En gros, ma_map["Fred"] est soit un nombre, soit un conteneur ; si
c'est un conteneur, tu peux écrire ma_map["Fred"]["truc"] ; sinon, tu
peux le convertir en un "Feuille&" (int dans ton cas).

NB : j'ai peu d'expérience dans ce type de structure, il doit être
possible de faire plus élégant.



--
http://www.giromini.org/usenet-fr/repondre.html

1 2