C++ concisely checking if item in STL container (e

2019-04-28 19:02发布

问题:

bool xInItems = std::find(items.begin(), items.end(), x) != items.end();

Is there a more concise way of checking if x is in items? This seems unnecessarily verbose (repeating items three times), which makes the intent of the code a little harder to read.

For example, is there something like the following:

bool xInItems = boost::contains(items, x);

If there doesn't exist any more concise boost/stl algorithm to check if a collection contains an item, is it considered good or bad practice to use instead a helper function to enable contains(items, x)?

Am I using the wrong STL container? Even a std::set would result in bool xInItems = items.find(x) != items.end(); which still seems verbose. Am I thinking about this the wrong way?

回答1:

If your data is sorted, you can use std::binary_search, which returns a bool:

bool xInItems = std::binary_search(items.begin(), items.end(), x));

If you really need to leave the items un-sorted, but have C++11 available, you could use std::any_of, but it requires a predicate, so it's likely to end up at least as verbose as std::find (and probably more so).



回答2:

It's not hard to write a template function from scratch.

template<typename T, typename Iterator>
bool contains(Iterator it1, Iterator it2, const T & value)
{
    return std::find(it1, it2, value) != it2;
}

template<typename T, typename Container>
bool contains(const Container & c, const T & value)
{
    return contains(c.begin(), c.end(), value);
}

You can even provide specializations for containers that have their own find function so that it's not calling std::find.



回答3:

any_of_equal will do the task:

#include <boost/algorithm/cxx11/any_of.hpp>

bool xInItems = boost::algorithm::any_of_equal(items, x);


回答4:

One easy way to find if an element is within a set is with:

container.find(x) != container.end()

So that if you are to use a set of integers, it could be something like:

stl::set<int> intSet;
intSet.insert(3);
if( intSet.find(3) != intSet.end()) 
      printf("Found it!");


回答5:

#include "boost/range/algorithm/find.hpp"

bool xInItems = boost::find(items, x) != items.end();

This is as concise as should be expected given the preference towards flexible iterator usage in C++.

You should probably just stick with std::find since it is idiomatic, and hope that eventually std::range will be accepted and provide a standard more concise alternative to iterator pairs.



标签: c++ boost stl