2009-12-03 8 views
22

J'ai un code python qui contient le code suivant.Traduction du dictionnaire python en C++

d = {} 

d[(0,0)] = 0 
d[(1,2)] = 1 
d[(2,1)] = 2 
d[(2,3)] = 3 
d[(3,2)] = 4 

for (i,j) in d: 
    print d[(i,j)], d[(j,i)] 

boucle Malheureusement sur toutes les clés en python est pas vraiment assez rapide pour mon but, et je voudrais traduire ce code C++. Quelle est la meilleure structure de données C++ à utiliser pour un dictionnaire python dont les clés sont des clés? Quel serait l'équivalent C++ du code ci-dessus?

J'ai regardé des matrices éparses dans la bibliothèque d'amplification, mais je n'ai pas trouvé de moyen facile de faire une boucle uniquement sur les éléments non nuls.

+0

Avez-vous envisagé une autre disposition des données. Si (i, j) est toujours associé à (j, i) alors vous n'aurez peut-être pas vraiment besoin des deux. Vous pourriez juste construire l'association au moment où vous construisez le dictionnaire. Vous pouvez simplement stocker une dict de (i, j) dans le magasin d'entrée (d (i, j), d (j, i)). Ceci suppose que les nombres dans le tuple pourraient être arbitrairement ordonnés, ce qui est probablement vrai. –

+0

Aussi, si vous marchez simplement les tuples, stockez-les dans une liste et parcourez la liste. –

Répondre

37

Un dictionnaire serait un std :: carte en C++, et un tuple avec deux éléments serait une paire std ::.

Le code python fourni se traduirait par:

#include <iostream> 
#include <map> 

typedef std::map<std::pair<int, int>, int> Dict; 
typedef Dict::const_iterator It; 

int main() 
{ 
    Dict d; 

    d[std::make_pair(0, 0)] = 0; 
    d[std::make_pair(1, 2)] = 1; 
    d[std::make_pair(2, 1)] = 2; 
    d[std::make_pair(2, 3)] = 3; 
    d[std::make_pair(3, 2)] = 4; 

    for (It it(d.begin()); it != d.end(); ++it) 
    { 
     int i(it->first.first); 
     int j(it->first.second); 
     std::cout <<it->second <<' ' 
       <<d[std::make_pair(j, i)] <<'\n'; 
    } 
} 
+2

C'est vraiment très bien. Bon travail. Très instructif pour quelqu'un comme moi travaillant sur la mise à niveau de leurs compétences de l'ancienne école C++ au C++ moderne. –

+1

'd [* it]' devrait être 'it-> second'' –

+0

' d [* it] 'donne des erreurs sur vsnet 2005. Essayez' it-> second''' – chollida

8

Le type est

std::map< std::pair<int,int>, int> 

Le code pour ajouter des entrées à la carte est comme ici:

typedef std::map< std::pair<int,int>, int> container; 

container m; 

m[ make_pair(1,2) ] = 3; //... 

for(container::iterator i = m.begin(); i != m.end(); ++i){ 
    std::cout << i.second << ' '; 
    // not really sure how to translate [i,j] [j,i] idiom here easily 
} 
+1

Vous ne pouvez pas utiliser 'typename' lorsque le type n'est pas un nom dépendant. –

+0

@Roger: vous avez raison, corrigé que "typename container :: iterator" – catwalk

4

Jetez un oeil à Boost.python. C'est pour l'interaction entre python et C++ (en construisant essentiellement des librairies python en C++, mais aussi pour l'intégration de python dans les programmes C++). La plupart des structures de données python et leurs équivalents C++ sont décrits (n'ont pas été vérifiés pour celui que vous voulez).

3

std::map ou plus probablement std::tr1::unordered_map/boost::unordered_map (aka hash_map) est ce que vous voulez.

Aussi, comme l'a dit kriss, Boost.Python est une bonne idée à regarder ici. Il fournit déjà une version C++ de la classe dict de python, donc si vous faites des choses multilingues, cela peut être utile.

0

En réponse directe à votre question (pour la partie python, regardez mon autre réponse). Vous pouvez oublier la partie tuple si vous le souhaitez. Vous pouvez utiliser toute clé/valeur de type de mappage (hachage, etc.) en C++, il vous suffit de trouver une fonction clé unique. Dans certains cas, cela peut être facile. Par exemple, si vous deux entiers sont des entiers compris entre 1 et 65536, vous pouvez simplement utiliser un entier de 32 bits avec chaque partie de 16 bits de l'une des clés. Un simple décalage et un 'ou' ou un + pour combiner les deux valeurs ferait l'affaire et c'est très efficace.

1

Voulez-vous appeler une routine C++ optimisée via Python? Si c'est le cas, lisez ceci:

Souvent, j'utilise PyYaml pour traiter des dictionnaires en Python. Peut-être que vous pourriez créer un lien dans quelque chose comme LibYAML ou yamlcpp à:

  1. Traduire un dictionnaire Python dans une chaîne YAML
  2. Utiliser Python pour appeler une fonction C++ compactés en utilisant quelque chose comme SWIG, en prenant la chaîne YAML comme paramètre.
  3. Utilisez une bibliothèque C++ pour analyser le YAML & obtenir un objet std::map
  4. Operate sur objet std :: carte

Attention: Je ne l'ai jamais essayé, mais en utilisant le moteur de recherche préféré de tout le monde sur "yaml std::map" donne beaucoup de liens intéressants

1

La carte est souvent implémentée sous la forme d'un arbre binaire équilibré et non d'une table de hachage. Ce n'est pas le cas pour un dict Python. Vous avez donc besoin d'une structure de données équivalente à C++ O (1) pour utiliser vos paires.