2009-11-27 13 views
6

Poiché non esiste una funzione membro .resize() in C++ std :: map Mi chiedevo come si possa ottenere una std :: map con al massimo n elementi .Come ottenere i primi n elementi di una std :: map

La soluzione ovvia è creare un ciclo da 0 a n e utilizzare l'ennesimo iteratore come primo parametro per std :: erase().

Mi chiedevo se c'è qualche soluzione che non ha bisogno del ciclo (almeno non nel mio codice utente) ed è più "il modo STL di andare".

+1

Hmm .. Direi che usare un ciclo iteratore * è * la via STL, no? – schnaader

+2

Non c'è 'std :: erase'. Usa 'std :: map : erase()' –

risposta

13

È possibile utilizzare std::advance(iter, numberofsteps) per quello.

+0

+1 - non lo sapevo, bello. – schnaader

0

Perché desideri ridimensionare una mappa?

Gli elementi di una mappa non vengono memorizzati in qualsiasi ordine - la prima 'n' in realtà non significa nulla

edit:
come È interessante notare che std :: map ha un ordine, non è sicuro utile questo concetto è.
Le voci sono nello stesso ordinamento dei tasti?
Che cosa significa? Se hai Nomi digitati da SSN vuol dire che i nomi sono memorizzati nell'ordine numerico SSN?

+0

Gli elementi non sono ordinati per chiave? –

+0

Non nel modo in cui pensi, gli elementi sono in qualche ordine in memoria. C'è un algoritmo di hash che converte la chiave in un indice. Ma gli elementi per key1 e key2 non sono necessariamente uno accanto all'altro. –

+3

@mgb No, sarebbe una tabella hash. Una std :: map è un albero di ricerca binario (solitamente un albero rosso-nero per essere specifico). Gli elementi di una std :: map sono quindi memorizzati in un modo che rende l'iterazione in ordine facile e veloce. – Tim

1

Una std :: map non è un elenco. Non ci sono elementi "primi n".

BTW: Gli iteratori non sono validi se il contenitore viene modificato.

Se hai davvero bisogno di una mappa più piccola, puoi iterarlo e aggiungere tutti gli elementi fino all'n-esima in una nuova mappa.

+3

Bene, gli elementi sono ordinati in base alla loro chiave, vero? – Nailer

+0

@Nailer: Bello, non lo sapevo. Questo collegamento conferma: http://www.cplusplus.com/reference/stl/map/ – ya23

+1

Sì, lo sono. Ma una mappa è "molto probabilmente implementata come un (equilibrato) albero di nodi" (citazione "Il linguaggio di programmazione C++", Bjarne Stroustrup), non una lista. Quindi mymap [n] non ha alcun senso. – EricSchaefer

3

Soluzione universale per quasi tutti i contenitori, come std :: list, std :: map, boost :: multi_index. Devi controllare solo la dimensione della tua mappa.

template<class It> 
It myadvance(It it, size_t n) { 
    std::advance(it, n); 
    return it; 
} 

template<class Cont> 
void resize_container(Cont & cont, size_t n) { 
    cont.erase(myadvance(cont.begin(), std::min(n, cont.size())), 
       cont.end()); 
} 
+0

è void std :: advance(), quindi questo non è stato compilato. – Norbert

+0

Giusto. Ho sistemato. –

+0

+1, ma se dovessi mettere in ordine questa versione per il rilascio dovresti decidere quale concetto funziona su 'resize_container'. I nomi dei parametri di funzione e modello suggeriscono qualsiasi contenitore. Il nome del parametro della funzione suggerisce qualsiasi mappa. Come scritto penso che funzionerà in realtà su qualsiasi Sequence o Container associativo, che purtroppo significa che il suo dominio è un gruppo polifletico nella tassonomia del C++. –

1

Il modo corretto è utilizzare std :: advance. Ma qui è un modo divertente (lento) che consente di "ridimensionare la mappa". Più in generale, questo tipo di trucco può essere utilizzato per altre cose che funzionano sul vettore ma non sulla mappa.

map<K,V> m; //your map 
vector< pair<K,V> > v(m.begin(), m.end()); 
v.resize(n); 
m = map<K,V>(v.begin(),v.end());