Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

trying to see if vector<string> has no values in map<string, string>

Tags:

c++

bind

boost

Just for fun I was trying to write a one line with std::find_if with boost::bind to check whether all the keys given in a vector in a map has no values, but really could not come up with a neat line of code.
Here is what I attempted

vector<string> v;  
v.push_back("a");  
v.push_back("2");  
...  
map<string, string> m;  
m.insert("b","f");  
...  
std::find_if(v.begin(), v.end(), boost::bind(&string::empty, boost::bind(&map<string,String>::operator[], _1), _2 )) != v.end();  

Obviously this is a big fail... anyone tried something like this?

like image 784
SWKK Avatar asked Jul 03 '26 07:07

SWKK


2 Answers

The following line of code returns true only if all elements from v are not present in m:

bool a = v.end() == std::find_if( v.begin(), v.end(), boost::bind( &str_map_t::const_iterator::operator!=, boost::bind<str_map_t::const_iterator>( &str_map_t::find, &m, _1 ), m.end() ) );

Explanation:

Here we have two functors:

  1. boost::bind<str_map_t::const_iterator>( &str_map_t::find, &m, _1 )
    This functor will return const_iterator which points to the element from m or to m.end() if not found. Here you should explicitly point return type str_map_t::const_iterator for boost::bind to get rid of ambiguity.

  2. boost::bind( &str_map_t::const_iterator::operator!=, _1, _2 )
    This one will return true if _1!=_2 and false otherwise.

Combine 1 and 2 and we'll get the full code:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
#include <map>    
#include <boost/bind.hpp>    
using namespace std;

int main(int argc, char *argv[])
{
    vector<string> v;
    v.push_back("x");
    v.push_back("a");
    v.push_back("6");

    typedef map<string, string> str_map_t;
    str_map_t m;
    m.insert( str_map_t::value_type( "b", "f" ) );

    bool a = 
      v.end() == std::find_if( 
        v.begin(), v.end(), 
          boost::bind( 
            &str_map_t::const_iterator::operator!=, 
            boost::bind<str_map_t::const_iterator>( &str_map_t::find, &m, _1 ), 
            m.end() 
          ) 
      );

    std::cout << a << endl;

    return 0;
}

I wouldn't say it is readable code and I'd recommend to write a custom functor to get it more readable. A more readable version could look like the following (without bind):

struct not_in_map {
    not_in_map( const str_map_t& map ) : map_(map) {}
    bool operator()( const string& val ) { return map_.end() != map_.find( val ); }
private:
    const str_map_t& map_;
};
bool a = v.end() == std::find_if( v.begin(), v.end(), not_in_map(m) );
like image 181
Kirill V. Lyadvinsky Avatar answered Jul 05 '26 21:07

Kirill V. Lyadvinsky


std::for_each(v.begin(), v.end(), [](std::string& ref) { if m.find(ref) != m.end() /* do something*/ });

Lambdas ftw.

like image 28
Puppy Avatar answered Jul 05 '26 22:07

Puppy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!