2011-09-07 14 views
6

Questa domanda è ispirata da another topic che pone questa domanda:Come posso far funzionare insieme std :: find_if e std :: map usando una libreria boost?

Trova il primo valore maggiore del valore specificato dall'utente da un contenitore di carta

che può essere risolto in diversi modi. Una tipica soluzione C++ 03 definisce una funzione dedicata (o un functor) e la passa a std::find_if come terzo argomento.

In C++ 11, si può evitare che definisce un dedicato funzione (o funtore), e possono invece utilizzare lambda come:

auto it = std:: find_if(m.begin(), mp.end(), 
        [n](const std::pair<std::string, int> & x) -> bool 
         { return x.second > n; } 
        ); 

che è the accepted answer.

Sto ancora cercando una soluzione breve e interessante. Se fosse un vettore, allora ho appena appreso una soluzione fresca che fa uso di Boost.Phoenix e la soluzione diventa molto conciso (ideone demo):

std::vector<int> v = ...; 
auto it = std::find_if(v.begin(), v.end(), arg1 > 4); 

Ecco arg1 è un oggetto funtore definito boost::phoenix::arg_names namespace, e l'espressione arg1>4 valuta un altro functor che viene passato a std::find_if.

Un test rapido è (ideone),

std::cout<< (arg1 > 9)(v) << std::endl; //prints 0 if as v > 9 is false, else 1 

//or store the functor first and then use it 
const auto & f = arg1 > 9; 
std::cout<< f(v) << std::endl; //prints 0 if as v > 9 is false, else 1 

La mia domanda è, voglio risolvere il problema carta, in modo simile. C'è una soluzione del genere? Qualcosa di simile:

auto it = std::find_if(m.begin(),mp.end(), (???).second > n); //m is std::map 

Oppure,

auto it = std::find_if(m.begin(),mp.end(), at<1>(arg1) > n); //m is std::map 

Per farlo funzionare, l'espressione at<1>(arg1) > 2 deve valutare ad un funtore che prende const std::pair & come argomento. I miei sentimenti istintivi mi dicono che boost ha questa soluzione. :-)

+0

Vuoi trovare solo i valori (in cui http caso: // www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/adaptors/reference/map_values.html è la risposta) o l'iteratore dell'intera chiave, coppia di valori in cui il valore ha soddisfatto il predicato ? – Cubbi

+0

@Cubbi: Questa non è la risposta se non funziona con 'std :: find_if' che restituisce un iteratore della mappa. – Nawaz

+0

@Nawaz: non so se std :: find_if è richiesto. In caso contrario, andrei con http://www.cplusplus.com/reference/stl/map/upper_bound/ che dovrebbe essere più veloce e solo una semplice riga di codice. –

risposta

9

Infatti, Boost.Fusion e Boost.Phoenix hanno esattamente ciò che si desidera integrare.

Se si include l'intestazione necessaria per adapt std::pair<> as a conforming Fusion sequence, allora si può usare la versione pigra di Phoenix di boost::fusion::at_c<> per accedere std::pair<>::first o std::pair<>::second (assicuratevi di #include <boost/phoenix/fusion.hpp>).

namespace phx = boost::phoenix; 
using phx::arg_names::arg1; 

auto it = std::find_if(m.begin(), m.end(), phx::at_c<1>(arg1) > n); 

EDIT: intero campione, testato con VC++ 2010 SP1 + Boost 1.47.0:

#include <algorithm> 
#include <map> 
#include <string> 
#include <iostream> 
#include <boost/fusion/include/std_pair.hpp> 
#include <boost/phoenix/core.hpp> 
#include <boost/phoenix/operator.hpp> 
#include <boost/phoenix/fusion.hpp> 

int main() 
{ 
    namespace phx = boost::phoenix; 
    using phx::arg_names::arg1; 

    std::map<std::string, int> m; 
    m["foo"] = 1; 
    m["bar"] = 2; 
    m["baz"] = 3; 
    m["qux"] = 4; 
    m["quux"] = 5; 
    m["corge"] = 6; 
    m["grault"] = 7; 
    m["garply"] = 8; 
    m["waldo"] = 9; 
    m["fred"] = 10; 
    m["plugh"] = 11; 
    m["xyzzy"] = 12; 
    m["thud"] = 13; 

    int const n = 6; 
    auto it = std::find_if(m.cbegin(), m.cend(), phx::at_c<1>(arg1) > n); 
    if (it != m.cend()) 
     std::cout << it->first << '\n'; // prints "fred" 
} 
+0

Si prega di inviare una soluzione completa funzionante e testata. Non voglio dire che non si compila o non funziona. Però, sto cercando di fare quello che mi hai suggerito. – Nawaz

+0

@Nawaz: Modificato. – ildjarn

+0

OK. Ho provato a compilarlo, e non è riuscito alla compilazione: http://ideone.com/EgALC – Nawaz

Problemi correlati