2009-12-03 29 views
22

Ho il codice Python che contiene il seguente codice.Traduzione del dizionario Python in 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)] 

Purtroppo loop su tutte le chiavi in ​​python non è in realtà abbastanza veloce per il mio scopo, e mi piacerebbe tradurre questo codice C++. Qual è la migliore struttura dati C++ da usare per un dizionario python che ha le tuple come chiavi? Quale sarebbe l'equivalente in C++ del codice sopra?

Ho esaminato le matrici sparse nella libreria boost, ma non ho trovato un modo semplice per eseguire il ciclo solo sugli elementi diversi da zero.

+0

Avete considerato un altro layout di dati. Se (i, j) è sempre accoppiato con (j, i), allora potrebbe non essere necessario entrambi. Potresti semplicemente costruire l'associazione nel momento in cui stai costruendo il dizionario. Si può semplicemente memorizzare un ditt di (i, j) in entrata (d (i, j), d (j, i)). Ciò presuppone che i numeri nella tupla possano essere ordinati arbitrariamente, il che è probabilmente vero. –

+0

Inoltre, se stai solo camminando con le tuple, salvale in un elenco e cammina nell'elenco. –

risposta

37

Un dizionario sarebbe uno std :: map in C++, e una tupla con due elementi sarebbe una std :: pair.

codice Il pitone fornito si tradurrebbe in:

#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

Questo è davvero molto bello. Buon lavoro. Molto istruttivo per qualcuno come me che lavora per aggiornare il proprio skillset dal vecchio linguaggio C++ al moderno C++. –

+1

'd [* it]' dovrebbe essere 'it-> second' –

+0

' d [* it] 'dà errori su vs.net 2005. Prova' it-> second' – chollida

8

Il tipo è

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

Il codice per aggiungere voci per mappare è come qui:

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

Non è possibile utilizzare 'typename' quando il tipo non è un nome dipendente. –

+0

@Roger: hai ragione, corretto quel "typename container :: iterator" – catwalk

4

Dai un'occhiata alla Boost.python. È per l'interazione tra Python e C++ (fondamentalmente costruendo lib di python usando C++, ma anche per incorporare python in programmi C++). La maggior parte delle strutture dei dati dei pitoni e dei loro equivalenti C++ sono descritti (non è stato controllato per quello che si desidera).

3

std::map o più probabile std::tr1::unordered_map/boost::unordered_map (alias hash_map) è ciò che si desidera.

Inoltre, come ha detto kriss, Boost.Python è una buona idea guardare qui. Fornisce già una versione C++ della classe dict di Python, quindi se stai facendo roba cross-language, potrebbe essere utile.

0

Come risposta diretta alla tua domanda (per la parte pitone guarda la mia altra risposta). Puoi dimenticare la parte della tupla se vuoi. Puoi usare qualsiasi tipo di chiave chiave/valore (hash, ecc.) In C++, devi solo trovare una funzione chiave univoca. In alcuni casi può essere facile. Ad esempio, se due interi sono interi tra 1 e 65536, è possibile utilizzare un intero a 32 bit con ogni parte di 16 bit uno dei tasti. Un semplice spostamento e un 'o' o + per combinare i due valori farebbero il trucco ed è molto efficiente.

1

Vuoi chiamare una routine C++ ottimizzata tramite Python? In tal caso, continua a leggere:

Spesso utilizzo PyYaml per i dizionari in Python. Forse è possibile collegare in qualcosa di simile LibYAML o yamlcpp a:

  1. tradurre un dizionario Python in una stringa YAML
  2. Usa Python per chiamare una funzione C++ avvolto usando qualcosa come SWIG, prendendo la stringa YAML come parametro.
  3. Utilizzare una libreria C++ per analizzare il YAML & ottenere un oggetto std::map
  4. operare su std :: map oggetto

Attenzione: non ho mai provato questo, ma utilizzando il motore di ricerca preferito da tutti su "yaml std::map" produce lotti di link interessanti

1

La mappa viene spesso implementata come albero binario bilanciato e non come tabella hash. Questo non è il caso di un ditt di Python. Quindi hai bisogno di una struttura dati equivalente a C++ O (1) per usare le tue coppie con.