This question already has answers here:
Why is there no transform_if in the C++ standard library?
(11 answers)
Closed 8 years ago.
Which algorithm or combine of algorithms can use for following situation?
struct Term
{
int ix;
double f;
};
std::vector<Term> terms = <intitalize terms>;
std::vector< int > termIxVector;
// NEED get all `ix` from the `terms` where term.f < 1.0,
// and insert 'ix' result to termIxVector.
//i.e. equavalent this loop:
for(std::size_t i = 0; i < terms.size(); ++i)
if ( terms[i].f < 1.0 )
termIxVector.push_back(terms[i].ix);
std::copy_if copies only Term structure. std::transform - doesn't support predicate.
Use std::for_each with a lambda
std::for_each(terms.begin(), terms.end(),
[&termIxVector](Term const& t) {
if(t.f < 1.0) termIxVector.push_back(t.ix);
});
Or a range based for
for(auto const& t : terms) {
if(t.f < 1.0) termIxVector.push_back(t.ix);
}
These kind of compositions of elementary algorithms are most conveniently done with Boost.Range:
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <iostream>
#include <iterator>
#include <vector>
struct Term
{
int ix;
double f;
};
int main()
{
using namespace boost::adaptors;
auto terms = std::vector<Term>{ {0, 0.1}, {1, 1.1}, {2, 0.8}, {3, 1.2}, {4, 0.9} };
auto termIxVector = terms
| filtered([](auto const& x){ return x.f < 1.0; }) // select
| transformed([](auto const& y){ return y.ix; }) // project
;
boost::copy(termIxVector, std::ostream_iterator<int>(std::cout, ","));
}
Live Example using Clang 3.5 SVN which prints the indices 0, 2, and 4 of your Term elements having a double less than 1.0.
NOTE: these ranges are lazily computed, and termIxVector is not a std::vector<int> actually. If you want that, you need to do something like
std::vector<int> termIxVector;
boost::push_back(termIxVector, /* RHS of the same range composition as above */);
If you really want to use std::copy_if, then an idea is to overload operator int() in the struct and use the standard std::copy_if with a unary predicate (lambda or functor), as this will allow you to convert Term to int. Code below:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
struct Term{
int ix;
double f;
operator int(){
return ix;
}
};
struct predicate{ // if you don't want a lambda
bool operator()(const Term& t){
return (t.f < 1.0 ? true : false);
}
};
int main()
{
std::vector<Term> terms = {{1, 0.1}, {2, 0.2}, {3, 1.1}, {4, 0.9}};
std::vector< int > termIxVector;
std::copy_if(terms.begin(), terms.end(),
back_inserter(termIxVector), predicate());
for(auto& elem: termIxVector)
std::cout << elem << std::endl;
}
Related
I have several sets of the same type:
std::set< TDate> spieltagDatum;
I would like to include all of them into a multimap of this type:
std::multimap<TDate, int> ereignis;
Is there an elegant possibility (perhaps with a lambda related function?) to include all members of ONE set into the multimap above not using the iterator mechanism? (The multimap pairs should be enriched with the INT parameter during insert).
I can suggest instead of iterators to use simplified for loop with auto like below.
I used integer TDate just for example, also instead of 123 in my code you may put any function for filling in values of multimap.
Try it online!
#include <map>
#include <set>
int main() {
using TDate = int;
std::set<TDate> spieltagDatum = {3, 5, 7};
std::multimap<TDate, int> ereignis;
for (auto & e: spieltagDatum)
ereignis.emplace(e, 123);
}
What do you mean by "not using the iterator mechanism"? (Don't use iterators at your own peril)
As you describe, what you do is to 1) transform (by enrich) and 2) insert, so the answer is std::tranform + std::insert.
#include <algorithm> // transform
#include <cassert>
#include <map>
#include <set>
int main() {
using TDate = int;
std::set<TDate> spieltagDatum = {3, 5, 7};
std::set<TDate> ...;
std::multimap<TDate, int> ereignis;
auto enrich = [](auto e){return std::make_pair(e, 123);};
std::transform(
begin(spieltagDatum), end(spieltagDatum),
std::inserter(ereignis, end(ereignis)),
enrich
);
... // repeat for other sets if necessary
assert( ereignis.find(5) != ereignis.end() );
assert( ereignis.find(5)->second == 123 );
}
https://godbolt.org/z/zzYbKK83d
A more declarative option using libraries, based on #prehistoricpenguin answer is:
(IMO it is worth mainly in C++17, where so many of the templates parameters are not really necessary)
#include <cassert>
#include <map>
#include <set>
#include <boost/iterator/transform_iterator.hpp>
int main() {
using TDate = int;
std::set<TDate> spieltagDatum = {3, 5, 7};
auto enriched = [](auto it){
return boost::transform_iterator(it, [](auto e){return std::pair(e, 123);});
};
std::multimap ereignis(
enriched(begin(spieltagDatum)),
enriched(end (spieltagDatum))
);
assert( ereignis.find(5) != ereignis.end() );
assert( ereignis.find(5)->second == 123 );
}
https://godbolt.org/z/6ajssjjjP
One possible answer is to write a convert iterator class, then we use the iterator to constructor the multimap instance.
#include <iostream>
#include <iterator>
#include <map>
#include <set>
template <typename KeyT, typename ValT>
class ConvertIter
: public std::iterator<std::forward_iterator_tag, std::pair<KeyT, ValT>> {
using SetIter = typename std::set<KeyT>::iterator;
public:
ConvertIter(SetIter itr, ValT v = ValT{}) : _itr(itr), _val(v) {}
bool operator==(const ConvertIter& other) { return other._itr == _itr; }
bool operator!=(const ConvertIter& other) { return other._itr != _itr; }
std::pair<KeyT, ValT> operator*() const {
return {*_itr, _val};
}
ConvertIter& operator++() {
++_itr;
return *this;
}
ConvertIter& operator++(int) {
++_itr;
return *this;
}
private:
SetIter _itr;
ValT _val;
};
int main() {
using TDate = int;
std::set<TDate> spieltagDatum = {3, 5, 7};
std::multimap<TDate, int> ereignis(
ConvertIter<TDate, int>(spieltagDatum.begin(), 123),
ConvertIter<TDate, int>(spieltagDatum.end()));
for (auto [date, val] : ereignis) {
std::cout << "[" << date << "," << val << "]" << std::endl;
}
return 0;
}
Demo:
https://godbolt.org/z/cr98f15jq
I'm trying to get the indices of one container where the elements match. Both containers are sorted in ascending order. Is there an algorithm or combo of algorithms that would place the indices of matching elements of sorted containers into another container?
I've coded an algorithm already, but was wondering if this has been coded before in the stl in some way that I didn't think of?
I would like the algorithm to have a running complexity comparable to the one I suggested, which I belive is O(min(m, n)).
#include <iterator>
#include <iostream>
template <typename It, typename Index_it>
void get_indices(It selected_it, It selected_it_end, It subitems_it, It subitems_it_end, Index_it indices_it)
{
auto reference_it = selected_it;
while (selected_it != selected_it_end && subitems_it != subitems_it_end) {
if (*selected_it == *subitems_it) {
*indices_it++ = std::distance(reference_it, selected_it);
++selected_it;
++subitems_it;
}
else if (*selected_it < *subitems_it) {
++selected_it;
}
else {
++subitems_it;
}
}
}
int main()
{
int items[] = { 1, 3, 6, 8, 13, 17 };
int subitems[] = { 3, 6, 17 };
int indices[std::size(subitems)] = {0};
auto selected_it = std::begin(items), it = std::begin(subitems);
auto indices_it = std::begin(indices);
get_indices(std::begin(items), std::end(items)
, std::begin(subitems), std::end(subitems)
, std::begin(indices));
for (auto i : indices) {
std::cout << i << ", ";
}
return 0;
}
We can use find_if to simplify the implementation of the function:
template<class SourceIt, class SelectIt, class IndexIt>
void get_indicies(SourceIt begin, SourceIt end, SelectIt sbegin, SelectIt send, IndexIt dest) {
auto scan = begin;
for(; sbegin != send; ++sbegin) {
auto&& key = *sbegin;
scan = std::find_if(scan, end, [&](auto&& obj) { return obj >= key; });
if(scan == end) break;
for(; scan != end && *scan == key; ++scan) {
*dest = std::distance(begin, scan);
++dest;
}
}
}
This doesn't make it that much shorter, but the code looks a little cleaner now. You're scanning until you find something as big as or equal to the key, and then you copy indicies to the destination as long as the source matches key.
maybe I misunderstodd the question. But there is a function in the algorithm library.
std::set_intersection
This does, what you want in one function. See:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main()
{
// Input values
std::vector<int> items{ 1,3,6,8,13,17 };
std::vector<int> subitems{ 3,6,17 };
// Result
std::vector<int> result;
// Do the work. One liner
std::set_intersection(items.begin(),items.end(), subitems.begin(),subitems.end(),std::back_inserter(result));
// Debug output: Show result
std::copy(result.begin(), result.end(), std::ostream_iterator<int>(std::cout, " "));
return 0;
}
If I misunderstood, then please tell me and I will find another solution.
EDIT:
I indeed misunderstood. You wanted the indices. Then maybe like this?
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using Iter = std::vector<int>::iterator;
int main()
{
// Input values
std::vector<int> items{ 1,3,6,8,13,17 };
std::vector<int> subitems{ 3,6,17 };
// Result
std::vector<int> indices{};
Iter it;
// Do the work.
std::for_each(subitems.begin(), subitems.end(), [&](int i) {it = find(items.begin(), items.end(), i); if (it != items.end()) indices.push_back(std::distance(items.begin(),it));});
// Debug output: Show result
std::copy(indices.begin(), indices.end(), std::ostream_iterator<int>(std::cout, " "));
return 0;
}
Unfortunately a very long "one-liner".
I need to think more . . .
The answer is yes but it will come with C++20:
you can use ranges for this purpose:
first make a view with some predicate you like:
auto result = items | ranges::view::filter(predicate);
then take the iterator to the original array from base, for example result.begin().base() will give you the iterator to the begin of result in the original array.
#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
#include <range/v3/view/filter.hpp>
#include <range/v3/view/transform.hpp>
int main()
{
std::vector<int> items = { 1, 3, 6, 8, 13, 17 };
std::vector<int> subitems = { 3, 6, 17 };
auto predicate = [&](int& n){
for(auto& s : subitems)
if(n == s)
return true;
return false;
};
auto result = items | ranges::view::filter(predicate);
for (auto& n : result)
{
std::cout << n << '\n';
}
for(auto it = result.begin(); it != result.end(); ++it )
std::cout << it.base() - items.begin() << ' ';
}
see the godbolt
By using std::set_intersection, defining an assignment_iterator class and a assignment helper, this is possible:
#include <iterator>
#include <iostream>
#include <algorithm>
#include <vector>
template <typename Transform>
class assignment_iterator
{
Transform transform;
public:
using iterator_category = std::output_iterator_tag;
using value_type = void;
using difference_type = void;
using pointer = void;
using reference = void;
assignment_iterator(Transform transform)
: transform(transform)
{}
// For some reason VC++ is assigning the iterator inside of std::copy().
// Not needed for other compilers.
#ifdef _MSC_VER
assignment_iterator& operator=(assignment_iterator const& copy)
{
transform.~Transform();
new (&transform) Transform(copy.transform);
return *this;
}
#endif
template <typename T>
constexpr assignment_iterator& operator=(T& value) {
transform(value);
return *this;
}
constexpr assignment_iterator& operator* ( ) { return *this; }
constexpr assignment_iterator& operator++( ) { return *this; }
constexpr assignment_iterator& operator++(int) { return *this; }
};
template <typename Transform>
assignment_iterator<Transform> assignment(Transform&& transform)
{
return { std::forward<Transform>(transform) };
}
int main()
{
int items[] = { 1, 3, 6, 8, 13, 17 };
int subitems[] = { 3, 6, 17 };
std::vector<int> indices;
std::set_intersection(std::begin(items), std::end(items)
, std::begin(subitems), std::end(subitems)
, assignment([&items, &indices](int& item) {
return indices.push_back(&item - &*std::begin(items));
})
);
std::copy(indices.begin(), indices.end()
, assignment([&indices](int& index) {
std::cout << index;
if (&index != &std::end(indices)[-1])
std::cout << ", ";
})
);
return 0;
}
Demo
It's more code, but maybe assignment is a more generic means to do other operations, that currently require a specific implementations like back_inserter and ostream_iterator, and thus be less code in the long run (e.g. like the other use above with std::copy)?
This should work properly all the time based on the documentation here:
elements will be copied from the first range to the destination range.
You can use std::find and std::distance to find the index of the match, then put it in the container.
#include <vector>
#include <algorithm>
int main ()
{
std::vector<int> v = {1,2,3,4,5,6,7};
std::vector<int> matchIndexes;
std::vector<int>::iterator match = std::find(v.begin(), v.end(), 5);
int index = std::distance(v.begin(), match);
matchIndexes.push_back(index);
return 0;
}
To match multiple elements, you can use std::search in similar fashion.
I have a 1D float array which represents a m *n (rows and columns) table of float values. My requirement is to find a min/max element for each row and column. For rows I can easily do it by using std::minmax_element by specifying a range of n elements. But for columns I need to use a stride iterator as elements are placed are not contiguous but placed at a step interval of n. Is there a standard iterator in boost/STL that can be used. The other option is to write my own version of it.
What is the best course ?
Two ways (among many) of doing it are using range-v3 (or boost::range) and boost::iterator.
With range-v3, it's immediate:
#include <iostream>
#include <range/v3/all.hpp>
using namespace ranges;
int main() {
std::vector<std::size_t> src{1, 2, 3, 4, 5, 6, 7};
const auto min_max = minmax(src | view::stride(3));
std::cout << min_max.first << " " << min_max.second << std::endl;
}
In boost::range, use boost::adaptors::strided.
#include <boost/range/adaptor/strided.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/assign.hpp>
#include <boost/range/algorithm.hpp>
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
using namespace boost::adaptors;
using namespace boost::assign;
std::vector<int> input;
int arr[] = {1, 2, 3, 4, 5, 6, 7};
auto str = std::make_pair(&arr[0], &arr[8]) | strided(3);
std::cout << *boost::range::min_element(str) << " " << *boost::range::max_element(str) << std::endl;
}
Note the following:
A range can be defined by a pair of iterators, so I used that here although a simpler form is possible (it fits your use case of heap-allocated C-style arrays).
Unfortunately, this sub-library doesn't seem to have min-max (or at least I couldn't find it), so there are two calls, one for min, and one for max.
Given a random-access iterator, it's not very difficult to build a strided forward boost::iterator_facade:
#include <iostream>
#include <vector>
#include <iterator>
#include <cstddef>
#include <algorithm>
#include <boost/iterator/iterator_facade.hpp>
template<typename It>
class stride_iterator :
public boost::iterator_facade<
stride_iterator<It>,
typename std::iterator_traits<It>::value_type,
boost::forward_traversal_tag> {
public:
stride_iterator() = default;
stride_iterator(It it, It end_it, std::size_t stride) :
m_it{it}, m_end_it{end_it}, m_stride{stride}
{}
private:
friend class boost::iterator_core_access;
void increment() {
if(std::distance(m_it, m_end_it) < m_stride) {
m_it = m_end_it;
return;
}
std::advance(m_it, m_stride);
}
bool equal(const stride_iterator<It> &other) const {
return m_it == other.m_it;
}
typename std::iterator_traits<It>::value_type &dereference() const {
return *m_it; }
It m_it, m_end_it;
std::size_t m_stride;
};
This should be enough for std::minmax_element. (Adding a bit of logic, the decrement and advance members, and changing the tag, would make it into a random-access iterator too.)
int main() {
using vec_t = std::vector<int>;
vec_t v{1, 2, 3, 4, 5, 6, 7};
stride_iterator<vec_t::iterator> b{std::begin(v), std::end(v), 3}, e{std::end(v), std::end(v), 3};
auto min_max = std::minmax_element(b, e);
std::cout << *min_max.first << " " << *min_max.second << std::endl;
}
Is there an std/boost algorithm to verify that all vectors within a vector have the same sizes? And by extension, that a property of all elements is the same?
In the below examples, I use the hypothetical std::all_equal that I am looking for:
typedef std::vector<int> Line;
std::vector<Line> lines;
lines.push(Line(10));
lines.push(Line(11));
auto equalLengths = std::all_equal(lines.begin(), lines.end(),
[](const Line& x){ return x.size(); });
(And by extension:
std::vector<MyClass> vec;
auto equal = std::all_equal(std::begin(vec), std::end(vec),
[](const MyClass& x) { return x.property(); });
)
How about
#include <algorithm> // for std::all_of
auto const required_size = lines.front().size();
std::all_of(begin(lines), end(lines),
[required_size](const Line& x){ return x.size() == required_size; });
Won't work for empty lists, unfortunately and you have to get the required size into the predicate somehow.
I like #ComicSansMS's answer, but if you want a slightly less-clear approach that also works on empty vectors, you could use std::adjacent_find with a custom predicate:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<std::vector<int>> vv{{3, 1}, {4, 1}, {5, 9}};
bool all_same_size = std::adjacent_find(
vv.cbegin(),
vv.cend(),
[](const std::vector<int>& a, const std::vector<int>& b) {
return a.size() != b.size(); // Look for two adjacent elements that
// have different sizes
}) == vv.cend();
std::cout << "all same size: " << all_same_size << '\n';
}
Is it possible/achievable to negate a boost filtered adaptor, e.g.
std::vector<int> v = {1, 2, 3, 4, 5};
for(auto i : v | !filtered(is_even))
std::cout << i << std::endl; // prints 1,3,5
instead of doing the negation inside the lambda expression?
Motivation: I work a lot with filtered and lambda functions, however when I use a filter more than once I usually refactor it into a custom filter, e.g.
for(auto i : v | even) // note: my filters are more complex than even.
std::cout << i << std::endl; // prints 2,4
Right now when I need the negation I am building a custom filter for them, e.g.
for(auto i : v | not_even)
std::cout << i << std::endl; // prints 1,2,3
but I would find it nicer to just be able to negate a filter, e.g.
for(auto i : v | !even)
std::cout << i << std::endl; // prints 1,2,3
Here's what I came up with on short notice:
#include <boost/range/adaptors.hpp>
#include <boost/functional.hpp>
#include <iostream>
namespace boost {
namespace range_detail {
template <typename T>
auto operator!(filter_holder<T> const& f) -> decltype(adaptors::filtered(boost::not1(f.val)))
{
return adaptors::filtered(boost::not1(f.val));
}
}
}
int main()
{
using namespace boost::adaptors;
int const v[] = { 1, 2, 3, 4 };
std::function<bool(int)> ll = [](int i){return 0 == (i%2);}; // WORKS
// bool(*ll)(int) = [](int i){return 0 == (i%2);}; // WORKS
// auto ll = [](int i){return 0 == (i%2);}; // not yet
auto even = filtered(ll);
for (auto i : v | !even)
{
std::cout << i << '\n';
}
}
See it live on liveworkspace.org
Note that it currently handles predicates of the form function pointer and std::function<...>, but not naked lambdas yet (on GCC 4.7.2)
This doesn't excactly answer the question, because it doesn't negate the filter, but only the predicate. I'm still posting this, because searching for the solution brought this question up as the first result.
Compared to the other answer, this has the advantage that we don't need to add custom code to namespace boost::range_detail.
C++17 Solution
The function std::not_fn can be used to create a negated predicate.
#include <boost/range/adaptors.hpp>
#include <functional>
#include <iostream>
struct is_even
{
bool operator()( int x ) const { return x % 2 == 0; }
};
int main()
{
using namespace boost::adaptors;
int const v[] = { 1, 2, 3, 4 };
for( auto i : v | filtered( std::not_fn( is_even{} ) ) )
{
std::cout << i << ' ';
}
}
Live Demo
C++11, C++14 Solution
The function std::not1 can be used to create a negated predicate. It has the additional requirement, that the predicate must define a member type, argument_type which has the same type as the predicates operator() parameter.
#include <boost/range/adaptors.hpp>
#include <functional>
#include <iostream>
struct is_even
{
using argument_type = int;
bool operator()( int x ) const { return x % 2 == 0; }
};
int main()
{
using namespace boost::adaptors;
int const v[] = { 1, 2, 3, 4 };
for( auto i : v | filtered( std::not1( is_even{} ) ) )
{
std::cout << i << ' ';
}
}
Live Demo