Related
Is there a way to find the minimum odd element of a vector of integers without basically reimplementing std::min_element and without doing additional work like computing the vector of odd integers first?
While a custom comparison object suggested in another answer will be a simple solution for std::min_element (and similar) in particular, it won't work with all standard algorithms. A general approach that works with any standard algorithm is to define a custom iterator.
Customising, combining and extending standard algorithms can nearly always be achieved with iterators. Writing custom iterators from scratch involves a lot of boilerplate and unfortunately standard doesn't provide templates for many iterator adaptors. Boost does provide plenty of iterator adaptor templates, and in this case boost::filter_iterator should prove useful.
Instead of the more traditional iterator algorithms, you could use range algorithms instead.
Since C++20, there are a host of standard range adaptors for range algorithms which are easy to compose:
auto it = std::ranges::min_element(
container | std::views::filter(condition)
);
Note that at the moment of writing, only libstdc++ has implemented the ranges standard library.
A simple solution consists in using a custom comparator function with sd::min_element.
What should be added in the following code is to check that the obtained value is odd indeed, as mentioned by #MSalters in their answer and by #Kevin in a comment.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> v = {0, 3, 4, 1};
auto comp = [](int a, int b) {
if ((a%2) and (b%2 == 0)) return true;
if ((a%2 == 0) and (b%2)) return false;
return a < b;
};
auto min_odd = std::min_element (v.begin(), v.end(), comp);
std::cout << *min_odd << std::endl;
}
A C++20 solution:
std::vector<int> ints{0, 1, 2, 3, 4, 5};
auto odd = [](int i) { return bool(i % 2); };
auto e = std::ranges::min_element(ints | std::views::filter(odd));
Yes, that's not very hard. Implement a custom comparison that sorts each even element above all odd elements. You still need to sort the odd elements in their usual order, and at the end check that there was at least one odd element in the vector.
Suppose you are given a vector of 2D points and are expected to find the point with the least Euclidean norm.
The points are provided as std::vector<point_t> points whith the following typedef std::pair<double, double> point_t. The norm can be calculated using
double norm(point_t p)
{
return pow(p.first, 2) + pow(p.second, 2);
}
Writing the loop myself I would do the following:
auto leastPoint = points.cend();
auto leastNorm = std::numeric_limits<double>::max();
for (auto iter = points.cbegin(), end = points.cend(); iter != end; ++iter)
{
double const currentNorm = norm(*iter);
if (currentNorm < leastNorm)
{
leastNorm = currentNorm;
leastPoint = iter;
}
}
But one should use STL algorithms instead of wirting one's own loops, so I'm tempted to to the following:
auto const leastPoint = std::min_element(points.cbegin(), points.cend(),
[](point_t const lhs, point_t const rhs){ return norm(lhs) < norm(rhs); });
But there is a caveat: if n = points.size() then the first implementation needs n evaluations of norm(), but the second implementation needs 2n-2 evaluations. (at least if this possible implementation is used)
So my question is if there exists any STL algorithm with which I can find that point but with only n evaluations of norm()?
Notes:
I am aware that big-Oh complexity is the same, but still the latter will lead to twice as many evaluations
Creating a separate vector and populating it with the distances seems a bit overkill just to enable the usage of an STL algorithm - different opinions on that?
edit: I actually need an iterator to that vector element to erase that point.
You could use std::accumulate (in the algorithm header):
Accumulate receive:
range
initial value
binary operator (optional, if not passed, operator+ would be called)
The initial value and every element of the range would be feed into the operator, the operator would return a result of the type of the initial value that would be feed into the next call to operator with the next element of the range and so on.
Example Code (Tested GCC 4.9.0 with C++11):
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
typedef std::pair<double, double> point_t;
struct norm_t {
point_t p;
double norm;
};
double norm(const point_t& p) {
return std::pow(p.first, 2) + std::pow(p.second, 2);
}
norm_t min_norm(const norm_t& x, const point_t& y) {
double ny = norm(y);
if (ny < x.norm)
return {y, ny};
return x;
}
int main() {
std::vector<point_t> v{{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}};
norm_t first_norm{v[0], norm(v[0])};
auto min_norm_point =
std::accumulate(v.begin(), v.end(), first_norm, min_norm);
std::cout << "(" << min_norm_point.p.first << "," << min_norm_point.p.second
<< "): " << min_norm_point.norm << '\n';
}
You could cache the minimum norm in the functor for avoid extra calculation (be aware: I'm using info about the implementation of std::min_element). The second element is the smallest found and the first is the iteration element.
struct minimum_norm {
minimum_norm() : cached_norm(-1) {}
bool operator()(const point_t& first, const point_t& second) {
if (cached_norm == -1)
cached_norm = norm(second);
double norm_first = norm(first);
if (norm_first < cached_norm) {
cached_norm = norm_first;
return true;
}
return false;
}
private:
double cached_norm;
};
int main()
{
std::vector<point_t> v{{3, 4}, {5, 6}, {1, 2}, {7, 8}, {9, 10}};
auto result = std::min_element(std::begin(v), std::end(v), minimum_norm());
std::cout << "min element at: " << std::distance(std::begin(v), result) << std::endl;
}
This is the sort of problem that boost::transform_iterator from the boost iterator library is designed to solve. There are limitations with the decorated iterator approach however and the C++ standards committee Ranges working group is looking into adding ranges to the standard which would potentially allow for a more functional approach of piping e.g. a transform to a min_element without needing temporary storage.
Eric Niebler has some interesting posts on ranges at his blog.
Unfortunately transform_iterator doesn't quite solve your problem given the way min_element is typically implemented - both iterators are dereferenced for each comparison so your function will still end up getting called more often than necessary. You could use the boost iterator_adaptor to implement something like a 'caching_transform_iterator' which avoids recomputing on each dereference but it would probably be overkill for something like norm(). It might be a useful technique if you had a more expensive computation though.
EDIT: Nevermind this, I misread the question.
I think you are mistaken in your assumption that min_element will perform 2N-2 comparisons
Per the c++ reference of min_element you can see that the algorithm performs essentially N comparison, which is the minimum for an unsorted array.
Here is a copy for the (very) unlikely case that www.cplusplus.com ever fails.
template <class ForwardIterator>
ForwardIterator min_element ( ForwardIterator first, ForwardIterator last )
{
if (first==last) return last;
ForwardIterator smallest = first;
while (++first!=last)
if (*first<*smallest) // or: if (comp(*first,*smallest)) for version (2)
smallest=first;
return smallest;
}
I've got a list of elements, say, integers and I want to check if my variable (another integer) is one of the elements from the list. In python I'd do:
my_list = [1,2,3,4] # elements
my_var = 3 # my variable
my_var in my_list # returns boolean
How to do that in C++? I thought of using std::list, but I can find no find method in it. I can see such method in std::set structure.
More deeply, the problem is that my program is given some unique ids (a list, a set, whatever) and I iterate over a long list of input data (ids) and check if they are included in the list (boolean value returned for each iteration step). And I'm not sure how should I do that in C++.
You can use std::find
bool found = (std::find(my_list.begin(), my_list.end(), my_var) != my_list.end());
You need to include <algorithm>. It should work on standard containers, vectors lists, etc...
std::list does not provide a search method. You can iterate over the list and check if the element exists or use std::find. But I think for your situation std::set is more preferable. The former will take O(n) time but later will take O(lg(n)) time to search.
You can simply use:
int my_var = 3;
std::set<int> mySet {1, 2, 3, 4};
if(mySet.find(myVar) != mySet.end()){
//do whatever
}
you must #include <algorithm>, then you can use std::find
They really should add a wrapper. Like this:
namespace std
{
template<class _container,
class _Ty> inline
bool contains(_container _C, const _Ty& _Val)
{return std::find(_C.begin(), _C.end(), _Val) != _C.end(); }
};
...
if( std::contains(my_container, what_to_find) )
{
}
A one-liner solution, similar to python, would be (std::set<int> {1, 2, 3, 4}).count(my_var) > 0.
Minimal working example
int my_var = 3;
bool myVarIn = (std::set<int> {1, 2, 3, 4}).count(my_var) > 0;
std::cout << std::boolalpha << myVarIn << std::endl;
prints true or false dependent of the value of my_var.
Use std::find, something like:
if (std::find(std::begin(my_list), std::end(my_list), my_var) != std::end(my_list))
// my_list has my_var
Declare additional helper function like this:
template <class T, class I >
bool vectorContains(const vector<T>& v, I& t)
{
bool found = (std::find(v.begin(), v.end(), t) != v.end());
return found;
}
And use it like this:
void Project::AddPlatform(const char* platform)
{
if (!vectorContains(platforms, platform))
platforms.push_back(platform);
}
Snapshot of example can be found here:
https://github.com/tapika/cppscriptcore/blob/b7f3d62747494a52a440482e841ffb016a3fc56e/SolutionProjectModel/Project.cpp#L13
Since C++20 you can use l.contains(my_var)
https://www.modernescpp.com/index.php/more-convenience-functions-for-containers-with-c-20
Is there a standard implementation of a for_each that does call with the element and the next one in the range?
For example take the range {0, 1, 2, 3, 4, 5}, I would like to call a function f with each element and its successor: {f(0, 1), f(1, 2), f(2, 3), f(3, 4), f(4, 5)}
Note how the last element is left out because it has no successor.
It would also be nice if there was a generalization of this to n successors that get passed with the element itself.
Up to now I have always solved this in terms of a handwritten loop with iterators.
However, I would like to go much more along the lines of C++11 range based for or std::for_each to avoid boiler plate code.
Examples
// today: handwritten loop
for(Range::iterator current = range.begin(); current != range.end(); ++current)
f(*current, *std::next(current));
// near future: wrapped version
for_each_pair(range.begin(), range.end(), f);
// slightly further future: generalized version
for_each_tuple<n>(range.begin(), range.end(), f);
Additional Question
The name of the function could be improved. To me for_each_pair/tuple sounds like all subsets of size n of the range should be returned (which is in itself another problem I would like to solve). So I'd like some suggestions on better names like:
for_each_adjacent<n>
Temporary Solution
I have posted my own solution over at CR. I won't duplicate it here because this is about a standard solution and there are already enough roll-your-own answers.
You could actually abuse std::unique or std::adjacent_find for this: the predicate is called with each consecutive pair in the iterator range, and as long as the predicate always returns false, it won't modify anything or return early.
Disregarding that particular hack, I would implement this as an iterator adapter, not an algorithm. That is, I'd implement a consecutive_tuple_iterator<N> which would return all tuples of N consecutive items. Then you could use it for things like count_if and includes, not just for_each. (It wouldn't be appropriate for most modifying algorithms, though.)
The simplest thing would be to write it as a generic algorithm, then apply it many times.
template< typename FwdIter, typename Func >
Func for_each_pair( FwdIter iterStart, FwdIter iterEnd, Func func )
{
if( iterStart == iterEnd )
return func;
FwdIter iterNext = iterStart;
++iterNext;
for( ; iterNext != iterEnd; ++iterStart, ++iterNext )
{
func( *iterStart, *iterNext );
}
return func;
}
As I was asked why it returns func (rather than void), this is typical of a for_each because of the fact that
func could be an object
It is passed by value.
func may "accumulate" some kind of state, but it is the copy we have made into this algorithm that is accumulating it, not the user's original object. We therefore pass them back the modified "func" object.
With C++ 11 and the new iterator helper functions std::next and std::prev for iterators, the second variant of the standard algorithm std::transform can be used to iterate over adjacent elements.
Here is an example that generates a list of adjacent pairs from a list:
std::vector<int> nums{3, 4, 2, 9, 15, 267};
std::vector<std::pair<int,int>> num_pairs;
if (!nums.empty()) {
std::transform(
std::begin(nums), std::prev(std::end(nums)),
std::next(std::begin(nums)),
std::back_inserter(num_pairs),
std::make_pair<
decltype(nums)::const_reference,
decltype(nums)::const_reference
>
);
}
Not exactly what you want, but take a look at cpplinq.
int numbers[] = {0, 1, 2, 3, 4, 5};
auto pairs = cpplinq::from_array(numbers)
>> cpplinq::pairwise()
>> cpplinq::to_vector(); // yields (0,1), (1,2), (2,3), (3,4), (4,5)
for(auto p : pairs)
f(p.first, p.second);
look out for C++23 views::slide(n)
vector<int> ints = {1, 2, 3, 4};
auto rg2 = ints | views::slide(2);
/*
{{1, 2}, {2, 3}, {3, 4}}
*/
auto rg3 = ints | views::slide(3);
/*
{{1, 2, 3},{2, 3, 4}}
*/
I have a Visual Studio 2008 C++03 application where I have two standard containers. I would like to remove from one container all of the items that are present in the other container (the intersection of the sets).
something like this:
std::vector< int > items = /* 1, 2, 3, 4, 5, 6, 7 */;
std::set< int > items_to_remove = /* 2, 4, 5*/;
std::some_algorithm( items.begin, items.end(), items_to_remove.begin(), items_to_remove.end() );
assert( items == /* 1, 3, 6, 7 */ )
Is there an existing algorithm or pattern that will do this or do I need to roll my own?
Thanks
Try with:
items.erase(
std::remove_if(
items.begin(), items.end()
, std::bind1st(
std::mem_fun( &std::set< int >::count )
, items_to_remove
)
)
, items.end()
);
std::remove(_if) doesn't actually remove anything, since it works with iterators and not containers. What it does is reorder the elements to be removed at the end of the range, and returns an iterator to the new end of the container. You then call erase to actually remove from the container all of the elements past the new end.
Update: If I recall correctly, binding to a member function of a component of the standard library is not standard C++, as implementations are allowed to add default parameters to the function. You'd be safer by creating your own function or function-object predicate that checks whether the element is contained in the set of items to remove.
Personally, I prefer to create small helpers for this (that I reuse heavily).
template <typename Container>
class InPredicate {
public:
InPredicate(Container const& c): _c(c) {}
template <typename U>
bool operator()(U const& u) {
return std::find(_c.begin(), _c.end(), u) != _c.end();
}
private:
Container const& _c;
};
// Typical builder for automatic type deduction
template <typename Container>
InPredicate<Container> in(Container const& c) {
return InPredicate<Container>(c);
}
This also helps to have a true erase_if algorithm
template <typename Container, typename Predicate>
void erase_if(Container& c, Predicate p) {
c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
}
And then:
erase_if(items, in(items_to_remove));
which is pretty readable :)
One more solution:
There is standard provided algorithm set_difference which can be used for this.
But it requires extra container to hold the result. I personally prefer to do it in-place.
std::vector< int > items;
//say items = [1,2,3,4,5,6,7,8,9]
std::set<int>items_to_remove;
//say items_to_remove = <2,4,5>
std::vector<int>result(items.size()); //as this algorithm uses output
//iterator not inserter iterator for result.
std::vector<int>::iterator new_end = std::set_difference(items.begin(),
items.end(),items_to_remove.begin(),items_to_remove.end(),result.begin());
result.erase(new_end,result.end()); // to erase unwanted elements at the
// end.
You can use std::erase in combination with std::remove for this. There is a C++ idiom called the Erase - Remove idiom, which is going to help you accomplish this.
Assuming you have two sets, A and B, and you want to remove from B, the intersection, I, of (A,B) such that I = A^B, your final results will be:
A (left intact)
B' = B-I
Full theory:
http://math.comsci.us/sets/difference.html
This is quite simple.
Create and populate A and B
Create a third intermediate vector, I
Copy the contents of B into I
For each element a_j of A, which contains j elements, search I for the element a_j; If the element is found in I, remove it
Finally, the code to remove an individual element can be found here:
How do I remove an item from a stl vector with a certain value?
And the code to search for an item is here:
How to find if an item is present in a std::vector?
Good luck!
Here's a more "hands-on" in-place method that doesn't require fancy functions nor do the vectors need to be sorted:
#include <vector>
template <class TYPE>
void remove_intersection(std::vector<TYPE> &items, const std::vector<TYPE> &items_to_remove)
{
for (int i = 0; i < (int)items_to_remove.size(); i++) {
for (int j = 0; j < (int)items.size(); j++) {
if (items_to_remove[i] == items[j]) {
items.erase(items.begin() + j);
j--;//Roll back the iterator to prevent skipping over
}
}
}
}
If you know that the multiplicity in each set is 1 (not a multiset), then you can actually replace the j--; line with a break; for better performance.