2012-03-23 10 views
5

quindi ho una serie di pairs<string ,string>C++ imposta la ricerca dell'elemento pair?

e voglio usare find() per cercare una singola stringa che sarebbe nella "prima" della coppia, quindi se trovo che stringa nella prima voglio tornare secondo da quella funzione.

Il mio tentativo attuale è ..

myList::iterator i; 

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

return i->second; 
+7

Perché non stai usando una 'mappa'? Altre note: se è un 'std :: set', perché si chiama' myList'? Hai creato una funzione di confronto per 'std :: pair's? Com'è? –

risposta

2

È possibile utilizzare std::set<std::pair<std::string, std::string> > per questo, ma avrete bisogno di un oggetto di confronto personalizzato per questo, perché operatore relazionale della coppia prende entrambi gli elementi per questo. Detto questo, sembra che in realtà dovresti usare un std::map<std::string, std::string>.

+1

Non sono d'accordo, la semantica sarebbe molto diversa, in particolare l'impossibilità di archiviare diversi oggetti con la stessa "chiave". Un "multimap" potrebbe essere più vicino in termini di semantica, ma non garantirebbe l'unicità della coppia che potrebbe anche essere desiderabile. Senza conoscere il requisito, la tua risposta è davvero uno sparo al buio ... –

1

La definizione di < per std::pair implementa un ordine lessicografico e "" è l'elemento minimo per le stringhe. Combinando questo otteniamo:

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; 
} 

Il trucco sta usando lower_bound in modo appropriato.

restituisce un iteratore che punta al primo elemento che non meno di confrontare value.

  • Se ritorna end(), allora non ha trovato nulla di interessante.
  • In caso contrario, it->first >= key così ci liberiamo del caso > (di alcun interesse per noi)

Vorrei sottolineare però che questo restituisce solo il primo elemento della gamma. Se siete interessati a tutti gli elementi, provare:

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)); 
} 

Ciò restituirà l'intera gamma di nodi in s il cui primo elemento è uguale a key. È quindi solo necessario iterare su questa gamma:

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

E non hanno nemmeno bisogno di preoccuparsi se il ritorno di lower_bound o upper_bound era alla fine o meno.

  • se lower_bound ritorni end(), così fa upper_bound, e il ciclo viene saltato
  • se lower_bound indica un nodo per cui it->first > key, poi upper_bound indicheranno che stesso nodo, e il ciclo viene saltato

Questa è la potenza degli intervalli: non è necessario effettuare controlli speciali, gli intervalli finiscono vuoti quando non c'è corrispondenza, quindi il ciclo su di essi viene saltato in un unico controllo.

+0

e se il secondo elemento fosse un int? – user3522401

6

C++ 11 è accettabile?

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

return it->second; 

O in C++ 03, prima definire un funtore:

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

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

     const string& realName; 
}; 

quindi chiamare in questo modo:

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

Questo restituirà solo la prima partita, ma dalla tua domanda, sembra che sia tutto ciò che ti aspetti.

Problemi correlati