How to filter items from a std::map?
You could use erase(), but I don't know how BOOST_FOREACH will handle the invalidated iterator. The documentation for map::erase states that only the erased iterator will be invalidated, the others should be OK. Here's how I would restructure the inner loop:
Actions::iterator it = _actions.begin();
while (it != _actions.end())
{
if (expired(*it))
{
bar(*it);
Actions::iterator toerase = it;
++it;
_actions.erase(toerase);
}
else
++it;
}
Modern way to filter STL container?
See the example from cplusplus.com for std::copy_if
:
std::vector<int> foo = {25,15,5,-5,-15};
std::vector<int> bar;
// copy only positive numbers:
std::copy_if (foo.begin(), foo.end(), std::back_inserter(bar), [](int i){return i>=0;} );
std::copy_if
evaluates the lambda expression for every element in foo
here and if it returns true
it copies the value to bar
.
The std::back_inserter
allows us to actually insert new elements at the end of bar
(using push_back()
) with an iterator without having to resize it to the required size first.
Filter the synthesized attribute through a std::map in a boost spirit semantic action
Reposting from comment
Try qi::_val = phx::ref(myMap)[qi::_1]
rather than qi::_val = phx::at(myMap, qi::_1)
.
How can I search an std::map using a key of a different type
With C++14 you can use heterogeneous lookup.
If you'd like to find an element with key that compares equivalent to the argument of std::map::find
, you should provide a Comparator as a third template parameter which should have Comparator::is_transparent
denoted as a type. It should also contain bool operator()
comparing your map key with any other type you'd like.
Funny description aside, here's an example:
struct X
{
int id;
int subid;
};
struct Details {};
struct Comparator
{
using is_transparent = std::true_type;
// standard comparison (between two instances of X)
bool operator()(const X& lhs, const X& rhs) const { return lhs.id < rhs.id; }
// comparison via id (compares X with integer)
bool operator()(const X& lhs, int rhs) const { return lhs.id < rhs; }
bool operator()(int lhs, const X& rhs) const { return lhs < rhs.id; }
// Same thing with Y
bool operator()(const X& lhs, const Y& rhs) const { return lhs.id < rhs.getId(); }
bool operator()(const Y& lhs, const X& rhs) const { return lhs.getId() < rhs.id; }
};
int main()
{
std::map<X, Details, Comparator> detailsMap = {
{ X{1, 2}, Details{} },
{ X{3, 4}, Details{} },
{ X{5, 6}, Details{} }
};
// it1 and it2 point to the same element.
auto it1 = detailsMap.find(X{1, 2});
auto it2 = detailsMap.find(1);
std::cout << detailsMap.size() << std::endl;
std::cout << std::boolalpha << (it1 == detailsMap.end()) << std::endl; // false
std::cout << std::boolalpha << (it1 == it2) << std::endl; // true
}
Note however that GCC didin't implement it until revision 219888.
returning a set of keys in the map matching the criteria
I think your solution is rather good: it is clear, and except if you can "guess" hash values based on the condition, I don't think you could be much more performant. However, you could change your function to make it more generic:
template<typename TKey, typename TValue, typename Predicate>
void filter (const map<TKey, TValue> & m,
set<TKey> & result,
Predicate & p)
{
typename map<TKey,TValue>::const_iterator it = m.begin();
typename map<TKey,TValue>::const_iterator end = m.end();
for( ; it != end ; ++it)
{
TKey key = it->first;
if (p(key))
result.insert(key);
}
}
Your example can then be writen using a functor as predicate:
struct Contains {
Contains(const string & substr) : substr_(substr) {}
bool operator()(const string & s)
{
return s.find(substr_) != string::npos;
}
string substr_;
};
The call to filter will then look like this:
map<string, Obj> m;
// Insert in m
set<string> res;
filter(m, res, Contains("stringToFind"));
std::transform with lambda: skip some items
template<class Src, class Sink, class F>
void transform_if(Src&& src, Sink&& sink, F&& f){
for(auto&& x:std::forward<Src>(src))
if(auto&& e=f(decltype(x)(x)))
*sink++ = *decltype(e)(e);
}
Now simply get a boost or std or std experiental optional. Have your f
return an optional<blah>
.
auto sink = std::inserter(first_to_last_name_map, first_to_last_name_map.begin());
using pair_type = decltype(first_to_last_name_map)::value_type;
transform_if(names, sink,
[](const std::string& i)->std::optional<pair_type>{
if (i == "bad")
return {}; // Don't Want This
else
return std::make_pair(i.substr(0,5), i.substr(5,5));
}
);
My personal preferred optional actually has begin end defined. And we get this algorithm:
template<class Src, class Sink, class F>
void polymap(Src&& src, Sink&& sink, F&& f){
for(auto&& x:std::forward<Src>(src))
for(auto&& e:f(decltype(x)(x)))
*sink++ = decltype(e)(e);
}
which now lets the f
return a range, where optional is a model of a zero or one element range.
How to filter object in c++
Keep it simple:
for (auto& c : myCells)
if (c.valueX > 5)
resultCells.push_back(c);
For your specific requirement ("write a function that gets vector of Cells, operator (gt - greater than, le - less or equal, and so on), name of a variable and an integer, and returns vector of Cells"), assuming "get" means "take as parameter":
vector<Cell> filter(vector<Cell> const& cells,
function<bool(int,int)> const& op,
int Cell::* var,
int i) {
vector<Cell> results;
for (auto& c : cells)
if (op(c.*var, i))
results.push_back(c);
return results;
}
Usage:
resultCells = filter(myCells, greater<int>(), &Cell::valueX, 5);
resultCells = filter(myCells, less<int>(), &Cell::valueY, 5);
resultCells = filter(myCells, equal_to<int>(), &Cell::ID, 5);
Related Topics
Is Std::Vector Copying the Objects with a Push_Back
Benchmarking (Python VS. C++ Using Blas) and (Numpy)
Getting an Accurate Execution Time in C++ (Micro Seconds)
How to Strip All Non Alphanumeric Characters from a String in C++
Is There Ever a Need for a "Do {...} While ( )" Loop
What Do Each Memory_Order Mean
What Does Flushing the Buffer Mean
How to Append an Int to a String in C++
When Should I Use C++14 Automatic Return Type Deduction
Variable Declarations in Header Files - Static or Not
How to Make an Expandable/Collapsable Section Widget in Qt
Set Precision of Std::To_String When Converting Floating Point Values
Getline Not Working Properly? What Could Be the Reasons
What Is the Proper Use of the Comma Operator
Why Does Printf("%F",0); Give Undefined Behavior