2011-09-07 13 views
6

Esta pregunta se inspira en another topic que plantea esta pregunta:¿Cómo puedo hacer que std :: find_if y std :: map trabajen juntos usando alguna biblioteca de impulso?

encontrar el primer valor mayor que el valor especificado por el usuario de un mapa de contenedores

que puede resolverse de varias maneras. Una solución típica de C++ 03 define una función dedicada (o functor) y la pasa a std::find_if como tercer argumento.

En C++ 11, se puede evitar que define una dedicado función (o funtor), y en su lugar puede hacer uso de lambda como:

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

que es the accepted answer.

Todavía estoy buscando una solución corta y genial. Si se tratara de un vector, entonces acabo de aprender una solución fría que hace uso de Boost.Phoenix y la solución se vuelve muy concisa (ideone demo):

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

Aquí arg1 es un objeto funtor se define en boost::phoenix::arg_names espacio de nombres, y la expresión arg1>4 evalúa a otro functor que luego pasa a std::find_if.

Una prueba rápida es (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 

Mi pregunta es, yo quiero resolver el problema mapa, de una manera similar. ¿Hay alguna solución? Algo así como:

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

O

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

para que funcione, la expresión at<1>(arg1) > 2 tiene que evaluar a un funtor que tiene const std::pair & como argumento. Mis sentimientos viscerales me dicen que el impulso tiene esta solución. :-)

+0

¿Quieres encontrar sólo los valores (en el que caso http: // www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/adaptors/reference/map_values.html es la respuesta) o el iterador a toda la clave, par de valores donde el valor satisface el predicado ? – Cubbi

+0

@Cubbi: Esa no es la respuesta si eso no funciona con 'std :: find_if' que devuelve un iterador del mapa. – Nawaz

+0

@Nawaz: No sé si se requiere std :: find_if. Si no, iría con http://www.cplusplus.com/reference/stl/map/upper_bound/, que debería ser más rápido, y con una sola línea de código simple. –

Respuesta

9

De hecho, Boost.Fusion y Boost.Phoenix tienen exactamente lo que usted desea incorporar.

Si se incluye el encabezado necesario adapt std::pair<> as a conforming Fusion sequence, entonces se puede utilizar la versión de Phoenix perezoso de boost::fusion::at_c<> acceder a std::pair<>::first o std::pair<>::second (Asegúrese de #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: la muestra completa, probada 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

Por favor, publique una solución completa que funcione y haya sido probada. No quiero decir que no compila o no funciona. Sin embargo, estoy tratando de hacer lo que sugirió. – Nawaz

+0

@Nawaz: Editado. – ildjarn

+0

De acuerdo. Intenté compilarlo y falló en la compilación: http://ideone.com/EgALC – Nawaz

Cuestiones relacionadas