2012-03-23 13 views
5

Así que tienen un conjunto de pairs<string ,string>C++ establece la búsqueda del elemento par?

y quiero utilizar find() para buscar una sola cadena que estaría en la "primera" de la pareja, a continuación, si encuentro esa cadena en la primera quiero volver segundo de esa función.

Mi intento actual es ..

myList::iterator i; 

i = theList.find(make_pair(realName, "*")); 

return i->second; 
+7

¿Por qué no estás usando un 'map'? Otras notas: si es un 'std :: set', ¿por qué se llama' myList'? ¿Has creado una función de comparación para 'std :: pair's? ¿Como se ve eso? –

Respuesta

2

Se puede utilizar para este std::set<std::pair<std::string, std::string> > pero se necesita un objeto de comparación personalizada para esto porque operador relacional de la pareja tiene en cuenta tanto los elementos de este. Dicho esto, parece que en realidad debería usar un std::map<std::string, std::string>.

+1

No estoy de acuerdo, la semántica sería bastante diferente, especialmente la incapacidad de almacenar varios elementos con la misma "clave". Un 'multimap' podría ser más cercano en términos de semántica, pero no garantizaría la singularidad del par, que también podría ser deseable. Sin conocer el requisito, tu respuesta realmente es una toma en la oscuridad ... –

1

La definición de < para std::pair implementa una orden lexicográfica y "" es el elemento mínimo para las cadenas. Combinando esto obtenemos:

typedef std::pair<std::string, std::string> StringPair; 
typedef std::set<StringPair> Set; 

std::string const* find_first(Set const& s, std::string const& key) { 
    Set::const_iterator const it = s.lower_bound(std::make_pair(key, "")); 

    // Check that it actually points to a valid element whose key is of interest. 
    if (it == s.end() or it->first != key) { return 0; } 

    // Yata! 
    return &it->second; 
} 

El truco está utilizando lower_bound adecuadamente.

Devuelve un iterador que apunta al primer elemento que no se compara con menos de value.

  • Si devuelve end(), entonces no se encontró nada interesante.
  • De lo contrario, it->first >= key por lo que deshacerse de la caja > (de ningún interés para nosotros)

me gustaría señalar sin embargo que esto sólo devuelve el primer elemento de la gama. Si usted está interesado en todos los elementos, tratar:

typedef std::pair<Set::const_iterator, Set::const_iterator> SetItPair; 

SetItPair equal_range_first(Set const& s, std::string const& key) { 
    StringPair const p = std::make_pair(key, ""); 
    return std::make_pair(s.lower_bound(p), s.upper_bound(p)); 
} 

Esto devolverá toda la gama de nodos en s cuyo primer elemento es igual a key. A continuación, sólo tiene que iterar sobre esta gama:

for (Set::const_iterator it = range.first; it != range.second; ++it) { 
    // do something 
} 

Y que ni siquiera tiene que preocuparse de si el retorno de lower_bound o upper_bound era el final o no.

  • si lower_bound rendimientos end(), entonces también lo hace upper_bound, y el bucle se salta
  • si lower_bound apunta a un nodo para el que it->first > key, entonces upper_bound señalarán a ese mismo nodo, y el bucle se salta

Esa es la potencia de los rangos: no es necesario hacer comprobaciones especiales, los rangos simplemente terminan vacíos cuando no hay coincidencia, por lo que el ciclo sobre ellos ... se omite en una sola comprobación.

+0

¿y si el segundo elemento es un int? – user3522401

6

¿Es C++ 11 aceptable?

auto it = find_if(theList.begin(), theList.end(), 
    [&](const pair<string, string>& val) -> bool { 
     return val.first == realName; 
    }); 

return it->second; 

O en C++ 03, primero definir un funtor:

struct MatchFirst 
{ 
     MatchFirst(const string& realName) : realName(realName) {} 

     bool operator()(const pair<string, string>& val) { 
       return val.first == realName; 
     } 

     const string& realName; 
}; 

luego llamarlo así:

myList::iterator it = find_if(a.begin(), a.end(), MatchFirst(realName)); 
return it->second; 

Esto sólo devolverá el primer partido, pero a partir de su pregunta, parece que eso es todo lo que estás esperando.

Cuestiones relacionadas