2009-11-27 14 views
6

Dado que no existe la función de miembro .resize() en C++ std :: map me preguntaba cómo se puede obtener un std :: map con un máximo de n elementos .Cómo obtener los primeros n elementos de un estándar :: map

La solución obvia es crear un bucle de 0 a n y usar el enésimo iterador como primer parámetro para std :: erase().

Me preguntaba si hay alguna solución que no necesite el bucle (al menos no en mi código de usuario) y es más "el camino de STL para ir".

+1

Hmm .. Yo diría que el uso de un bucle de iterador * es * el camino de STL a seguir, ¿no? – schnaader

+2

No hay 'std :: erase'. Use 'std :: map :: erase()' –

Respuesta

13

Puede usar std::advance(iter, numberofsteps) para eso.

+0

+1 - no lo sabía - bueno. – schnaader

0

¿Por qué le gustaría cambiar el tamaño de un mapa?

Los elementos de un mapa no se almacenan en cualquier orden - el primer 'n' no significa nada

edición:
Curiosamente std :: mapa tiene un pedido, no está seguro de lo útil este concepto es
¿Están las entradas en el mismo orden que las claves?
¿Qué significa eso? Si tiene Nombres codificados por SSN ¿significa eso que los nombres están almacenados en orden numérico de SSN?

+0

¿No son los elementos ordenados por la clave? –

+0

No en la forma en que piensas, los elementos están en algún orden en la memoria. Hay un algoritmo hash que convierte la clave en un índice. Pero los elementos para key1 y key2 no son necesariamente uno al lado del otro. –

+3

@mgb No, eso sería una tabla hash. Un std :: map es un árbol de búsqueda binaria (generalmente un árbol rojo-negro para ser específico). Por lo tanto, los elementos en un std :: map se almacenan de una manera que hace que iterar en orden sea fácil y rápido. – Tim

1

A std :: map no es una lista. No hay "primeros n" elementos.

BTW: los iteradores no son válidos si se cambia el contenedor.

Si realmente necesita un mapa más pequeño, puede repetirlo y agregar todos los elementos hasta la n-ésima posición en un nuevo mapa.

+3

Bueno, los elementos están ordenados por su clave ¿no? – Nailer

+0

@Nailer: Bien, no sabía eso. Este enlace confirma: http://www.cplusplus.com/reference/stl/map/ – ya23

+1

Sí, lo son. Pero un mapa es "muy probablemente implementado como un árbol (equilibrado) de nodos" (cita "El lenguaje de programación C++", Bjarne Stroustrup), no una lista. Entonces mymap [n] no tiene ningún sentido. – EricSchaefer

3

Solución universal para casi cualquier contenedor, como std :: list, std :: map, boost :: multi_index. Debes verificar el tamaño de tu mapa solamente.

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

es nulo std :: advance(), por lo que no se compiló. – Norbert

+0

Derecha. Lo arreglé –

+0

+1, pero si estuviera preparando esto para su lanzamiento, tendría que decidir qué concepto 'resize_container' opera. Los nombres de los parámetros de funciones y plantillas sugieren cualquier contenedor. El nombre del parámetro de función sugiere cualquier mapa. Tal como está escrito, creo que de hecho funcionará en cualquier Secuencia o Contenedor Asociativo, lo que desafortunadamente significa que su dominio es un grupo polifilético en la taxonomía C++. –

1

La forma correcta de hacerlo es usar std :: advance. Pero aquí hay una forma divertida (lenta) que permite 'usar el tamaño en el mapa'. De manera más general, este tipo de truco se puede usar para otras cosas que funcionan en vectores pero no en mapas.

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()); 
Cuestiones relacionadas