create container from another container, applying each element some function in c++ - c++

My question is simple, see example:
std::array<int,6> a = {{0,1,2,3,4,5}}; // -- given container.
auto F = []( int i ) { return i*i; }; // -- given function.
std::vector<int> v; // need create
// my solution:
v.reserve( a.size () );
for( std::size_t i = 0; i < a.size(); ++i )
v.push_back( F(a[i]) );
// but I need something like
std::vector<int>v( a.begin(), a.end(), <|applying each element to F|> );
Can I create container something like above not calling reserve explicitly and any reallocation?
EDIT:
I want avoid reserve; because othercase my first solution is good
for me :)
I want avoid any resize; because it's initialzed each
element by default ctor.
I will use this in the real project which may included many 3-rd party libraries ( boost, Soft-STL, ...).

The standard algorithm std::transform does exactly this!
std::vector<int> v(a.size());
std::transform(
std::begin(a), std::end(a),
std::begin(v),
F
);
You can start with an empty vector and use std::back_inserter, if you like:
std::vector<int> v;
std::transform(
std::begin(a), std::end(a),
std::back_inserter(v),
F
);
But you're subjecting yourself to needless re-allocations if you do that (unless you reserve first, as in your original attempt). You can decide for yourself what your priority is.

Use std::transform:
#include <algorithm> // std::transform
#include <iterator> // std::back_inserter
....
transform(a.begin(), a.end(), back_inserter(v), F);
You may want to call v.reserve(asize()) first to avoid re-allocations.

Another solution is to use boost::transform_iterator. The benefit is that you can pass iterators to the container constructor. That avoids memory reallocations compared to when using std::back_inserter or having to call reserve or resize on the destination. All in one statement:
std::vector<int> result(
boost::make_transform_iterator(std::begin(a), F)
, boost::make_transform_iterator(std::end(a), F)
);
You can achieve terser syntax though, like this:
std::vector<int> result(transform_range(a, F));
transform_range implementation:
template<class Iterator>
struct AutoSequence
{
Iterator const beg_, end_;
template<class T>
operator std::vector<T>() const {
return {beg_, end_};
}
};
template<class Function, class InSeq>
auto transform_range(InSeq const& in) -> AutoSequence<decltype(boost::make_transform_iterator<Function>(in.begin()))> {
return {
boost::make_transform_iterator<Function>(std::begin(in))
, boost::make_transform_iterator<Function>(std::end(in))
};
}
template<class Function, class InSeq>
auto transform_range(InSeq const& in, Function&& f) -> AutoSequence<decltype(boost::make_transform_iterator(in.begin(), f))> {
return {
boost::make_transform_iterator(std::begin(in), f)
, boost::make_transform_iterator(std::end(in), f)
};
}

Related

Using max<int> as a predicate breaks in C++11

In C++03 the following code works fine:
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
std::vector<int> v2;
v2.push_back(2);
v2.push_back(3);
v2.push_back(4);
std::transform(v.begin(), v.end(), v2.begin(), v2.begin(), std::max<int>);
return 0;
}
In C++11 this doesn't work because it added an overload for std::max that contains an initializer_list. Therefore, you have to use a very ugly cast to choose the correct overload:
static_cast<const int& (*)(const int&, const int&)>(std::max)
I have a few questions.
Why did the standard committee decide to do this knowing it would (probably) break existing code and force the user to create an ugly cast?
Are future standards of C++ going to attempt to alleviate this problem?
What is a workaround?
If you are doing this sufficiently frequently, you might want to write a transparent functor wrapper:
struct my_max {
template<class T>
const T& operator()(const T& a, const T& b) const{
return std::max(a, b);
}
};
Then you can simply do
std::transform(v.begin(), v.end(), v2.begin(), v2.begin(), my_max());
whenever you need it, rather than writing a lambda or a cast each time. This is basically the same idea as the transparent operator functors - let the template arguments be deduced at the actual call site rather than explicitly specified when you create the functor.
If you want to make this fancier, you can even have operator() take heterogeneous types and add perfect forwarding and use trailing return types:
struct my_max {
template<class T, class U>
constexpr auto operator()( T&& t, U&& u ) const
-> decltype(t < u ? std::forward<U>(u) : std::forward<T>(t)){
return t < u ? std::forward<U>(u) : std::forward<T>(t);
}
};
In C++14, this is simplified to
struct my_max {
template<class T, class U>
constexpr decltype(auto) operator()( T&& t, U&& u ) const{
return t < u ? std::forward<U>(u) : std::forward<T>(t);
}
};
What is a workaround?
A lambda is probably the most readable and useful for predicates and comparators:
std::transform(v.begin(), v.end(), v2.begin(), v2.begin(),
[] (int a, int b) {return std::max(a,b);} );
You might want to check out T.C.s functor if you need it more often. Or, with C++14:
auto max = [] (auto&& a, auto&& b) -> decltype(auto)
{return a > b? std::forward<decltype(a)>(a) : std::forward<decltype(b)>(b);};
Why did the standard committee decide to do this knowing it would
(probably) break existing code and force the user to create an ugly
cast?
The only explanation is that they found the new overload to bring enough joy to compensate the breaking of existing code and the need for workarounds in future.
You could just use std::max_element instead of this new overload, so you trade the syntax sugar for passing std::max-specializations as predicates for the syntax sugar of finding the maximum element within a couple of variables without explicitly creating an array for it.
Basically
std::transform( ..., std::max<int> );
// <=>
std::transform( ..., [] (int a, int b) {return std::max(a,b);} );
vs
int arr[] {a,b,c,d}; // You don't have an array with a,b,c,d included consecutively yet
int maximum = *std::max_element( std::begin(arr), std::end(arr) ); // ensure arr non-empty!
// <=>
auto maximum = std::max({a, b, c, d});
Maybe it does compensate? On the other hand, you barely ever need the latter.
Are future standards of C++ going to attempt to alleviate this
problem?
I don't think so. Apparently, the standard committee really doesn't like to remove recently introduced features. I don't really see that much of a problem either; The lambda does the job.
Although I've accepted T.C's answer which provides a comprehensive breakdown, as stated in a comment, I want to mimic the transparent comparator functor for class templates like std::less. This answer is provided for critique by others incase there's anything wrong with the syntax.
template <typename T = void>
struct my_max;
template <>
struct my_max<void> {
template<class T, class U>
constexpr decltype(auto) operator()( T&& t, U&& u ) const {
return t < u ? std::forward<U>(u) : std::forward<T>(t);
}
};
If you are ok with using C++20 ranges additions you can just use std::ranges::max.
std::ranges::max is not a function, but a struct so it can be passed to the algorithms.
Example:
#include <iostream>
#include <algorithm>
#include <vector>
#include <fmt/ranges.h>
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
std::vector<int> v2;
v2.push_back(2);
v2.push_back(3);
v2.push_back(4);
std::transform(v.begin(), v.end(), v2.begin(), v2.begin(), std::ranges::max);
std::cout << fmt::format("{}", v2);
}
If you have recent boost you can use BOOST_HOF_LIFT macro.
fmt lib in example is just for printing vector, all you need is boost
#include <type_traits>
#include <cassert>
#include <iostream>
#include <algorithm>
#include <vector>
#include <boost/hof/lift.hpp>
#include <fmt/ranges.h>
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
std::vector<int> v2;
v2.push_back(2);
v2.push_back(3);
v2.push_back(4);
std::transform(v.begin(), v.end(), v2.begin(), v2.begin(), BOOST_HOF_LIFT(std::max<int>));
std::cout << fmt::format("{}", v2);
}

How to transform map into vector using transform function template

I want to transform a map into vector.
int main()
{
map <int,int> m;
m[0]=99;
m[1]=5;
vector<int> v;
transform( m.begin(), m.end(), back_inserter( v ), ??? );
}
Which function i can use from STL in place of ???. I did a lot of googling, but didnt find out any.
Any discussion will be helpful.
Either with a lambda:
transform(m.begin(), m.end(), back_inserter(v),
[](pair<const int, bool> const & p) { return p.second; });
Or with a simple loop:
for (const auto & p : m) { v.push_back(p.second); }
Or with an old-style loop:
for (map<int, bool>::const_iterator it = m.begin(); it != m.end(); ++it)
{ v.push_back(it->second); }
In any case, call v.reserve(m.size()) beforehand to avoid reallocations.
Here's an example of how you can store the bool values in a std::vector at the unsequential indexes used as keys in the std::map (sort of like a hash bucket).
std::vector<bool> v(m.rbegin()->first + 1, false);
for (auto& p : m) {
v[p.first] = p.second;
}
The std::vector will be initialized with as many (false) values so that the biggest key number in the std::map will fit. The smallest number used as key must be greater or equal to zero.
Live example: http://ideone.com/5VQFmr
I suppose here's what you need (in C++11):
auto transformer = [] (const pair<const int, bool>& value) {
return value.second;
};
transform( m.begin(), m.end(), back_inserter( v ), transformer);
You can avoid C++11 lambda's if you want writing your own functor class, but the argument of operator() should be the same.
UPD. My original answer was wrong, because I wrote pair<int, bool> instead of pair<const int, bool>. This mistake shows importance of typedefs: if you used
typedef map<int, bool> MyMapT;
instead of plain map definition, you could write the type as MyMapT::value_type. It is way easier to understand and prevents you from making unnecessary temporaries as I did before.

how to pass a predicate to algorithm

I'm having a problem passing predicate using lambda, I'm trying to move element that matches the predicate to the beginning of a second container, but it didn't seem to work, so what's wrong please?
#include <iostream>
#include <vector>
#include <list>
#include <iterator>
#include <utility>
#include <algorithm>
using namespace std;
template <typename iterator, typename Container, typename T>
void move_if(iterator b, iterator e, Container o, T pred)
{
if(pred)
{
o.insert(o.begin(),pred);
}
}
int main()
{
vector<int>v{1,2,3,4,5,6,7,8,9,10};
vector<int>v2;
for (auto i=v.begin(); i !=v.end(); ++i)
save_if(v.begin(), v.end(), v2, []( vector<int>::iterator i){return (*i>5);});
return 0;
}
Try this...
int main()
{
std::vector<int> v{1,2,3,4,5,6,7,8,9,10};
std::vector<int> v2;
std::vector<int>::const_iterator
it = std::remove_copy_if(v.begin(), v.end(),
std::back_inserter(v2),
[](int const& i){return i <= 5;});
v.erase(it, v.end);
return 0;
}
You can read more about remove_copy_if on cppreference.com; it removes elements from the input range and copies them to the output unless the predicate returns true.
Note that this is an STL remove, so you need to call erase afterwards to shrink the input. The semantics of this solution are slightly different to the code you posted, but more similar to your description of what you wanted.
Check this out, I did some modifications on your code:
template <typename iterator, typename Container, typename T>
void move_if(iterator a, iterator b, Container &o, T pred)
{
for (auto i = a; i != b; i++)
{
if (pred(*i))
o.insert(o.begin(), *i);
}
}
int main()
{
vector<int>v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
vector<int>v2;
move_if(v.begin(), v.end(), v2, [](int i) { return !(i > 5); });
}
Note: As the comments, It's recommended to rename move_if to copy_if, if the functionality is as above code, otherwise you should really move items.
There is no overload of std::vector::insert that takes a predicate as second argument, so this line is wrong:
o.insert(o.begin(),pred);
Furthermore, the predicate needs to be called with an argument,
pred(someArg);
which in your case would be an std::vector<int>::iterator. Also, save_if is not the same as move_if. But more importantly, it isn't clear at all what you are trying to achieve.
In C++11, stateless lambdas like [](){return true} that do not capture anything can be implicitly converted to function pointers. When you do if(pred) you are converting your stateless lambda into a function pointer, checking if that pointer is non-null (it is non-null). This is not what you want to do.
Here is an implementation that moves things between b and e that pred(x) says should be moved:
template <typename iterator, typename Container, typename T>
void move_if(iterator b, iterator e, Container o, T pred)
{
for( auto i = b; i != e;++i) {
if(pred) {
o.insert(o.end(),std::move(*i));
}
}
}
Note that I inserted at o.end(), because the Container you want is probably vector, and inserting at the end() of vector is much faster.
In reality, you probably want to take an output iterator (and by default, use std::back_inserter from a Container) and output your data to that. Similarly, remove_move_if would be a better way to remove, shuffling the elements down the b-e range, and returning an iterator.
Finally, ranged-based algorithms are worth writing. Instead of taking a begin/end iterator pair, take a single object upon which begin(c) and end(c) have been overriden to return begin/end. If you are working on a sub-range, you can pass in a begin/end range of iterators struct with begin/end suitably overridden.

c++ boost conditional remove from container

i want to do something like c# linq style :
SomeColection <SomeType> someColection;
someColection.Remove(something => something > 2);
and it'll remove all the things that are bigger then 2 (or any other boolean condition)...
using boost in the project...
C++0x (using lambdas):
container.erase( std::remove_if( container.begin(), container.end(),
[]( int v ) { return v > 2; } ),
container.end() );
The reason for the erase combined with the remove_if is that STL algorithms apply to iterators, and not containers. They relocate the contents of the container, but they do not modify the container per-se.
C++03:
container.erase( std::remove_if( container.begin(), container.end(),
std::bind2nd( std::greater<int>(), 2 ) ),
container.end() );
This may seem a little simpler, but it is also less flexible, as there are only so many predicates already defined. For more complex operations you would have to write your own predicate functor.
You don't need boost (unless your main focus is that inline anonymous function). Plain STL is fine.
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
int main () {
std::vector<int> x (24);
for (int i = 0; i < x.size(); ++ i)
x[i] = i % 5;
std::vector<int>::iterator
new_end = std::remove_if(x.begin(), x.end(),
std::bind2nd(std::greater<int>(), 2));
x.erase(new_end, x.end());
for (int i = 0; i < x.size(); ++ i)
std::cout << x[i] << " ";
return 0;
}
With boost you can replace the bind2nd stuff with
#include <boost/lambda/lambda.hpp>
...
using boost::lambda::_1;
std::vector<int>::iterator new_end = std::remove_if(x.begin(), x.end(), _1 > 2);
First, you need a simple template wrapper:
template <class Container, class UnaryPredicate>
void erase_if(Container& container, UnaryPredicate pred)
{
container.erase(
std::remove_if(container.begin(), container.end(), pred),
container.end()
);
}
It's a well-known idiom, however it won't be possible with map or set as they maintain their own order.
Then, you can use Boost.Lambda to get the syntax you wish for writing the predicate itself.
using boost::lambda::_1;
SomeCollection<Type> someCollection;
erase_if(someCollection, _1 > 2);
By the way, boost::range v.1.46.0 (released in 2011) has exactly what you want - the remove_erase_if algorithm
#include <boost/range/algorithm_ext/erase.hpp
std::vector<int> vec = {1, 6, 2, 7};
boost::range::remove_erase_if(vec, [](int val){return val > 5;});
Short and straightforward.

Copy map values to vector in STL [duplicate]

This question already has answers here:
How to retrieve all keys (or values) from a std::map and put them into a vector?
(24 answers)
Closed 1 year ago.
Working my way through Effective STL at the moment. Item 5 suggests that it's usually preferable to use range member functions to their single element counterparts. I currently wish to copy all the values in a map (i.e. - I don't need the keys) to a vector.
What is the cleanest way to do this?
You could probably use std::transform for that purpose. I would maybe prefer Neils version though, depending on what is more readable.
Example by xtofl (see comments):
#include <map>
#include <vector>
#include <algorithm>
#include <iostream>
template< typename tPair >
struct second_t {
typename tPair::second_type operator()( const tPair& p ) const { return p.second; }
};
template< typename tMap >
second_t< typename tMap::value_type > second( const tMap& m ) { return second_t< typename tMap::value_type >(); }
int main() {
std::map<int,bool> m;
m[0]=true;
m[1]=false;
//...
std::vector<bool> v;
std::transform( m.begin(), m.end(), std::back_inserter( v ), second(m) );
std::transform( m.begin(), m.end(), std::ostream_iterator<bool>( std::cout, ";" ), second(m) );
}
Very generic, remember to give him credit if you find it useful.
You can't easily use a range here because the iterator you get from a map refers to a std::pair, where the iterators you would use to insert into a vector refers to an object of the type stored in the vector, which is (if you are discarding the key) not a pair.
I really don't think it gets much cleaner than the obvious:
#include <map>
#include <vector>
#include <string>
using namespace std;
int main() {
typedef map <string, int> MapType;
MapType m;
vector <int> v;
// populate map somehow
for( MapType::iterator it = m.begin(); it != m.end(); ++it ) {
v.push_back( it->second );
}
}
which I would probably re-write as a template function if I was going to use it more than once. Something like:
template <typename M, typename V>
void MapToVec( const M & m, V & v ) {
for( typename M::const_iterator it = m.begin(); it != m.end(); ++it ) {
v.push_back( it->second );
}
}
With C++11 we have the fancy new for loop:
for (const auto &s : schemas)
names.push_back(s.second);
where schemas is a std::map and names is an std::vector.
This populates the array (names) with values from the map (schemas); change s.second to s.first to get an array of keys.
#include <algorithm> // std::transform
#include <iterator> // std::back_inserter
std::transform(
your_map.begin(),
your_map.end(),
std::back_inserter(your_values_vector),
[](auto &kv){ return kv.second;}
);
Sorry that I didn't add any explanation - I thought that code is so simple that is doesn't require any explanation.
So:
transform( beginInputRange, endInputRange, outputIterator, unaryOperation)
this function calls unaryOperation on every item from inputIterator range (beginInputRange-endInputRange). The value of operation is stored into outputIterator.
If we want to operate through whole map - we use map.begin() and map.end() as our input range. We want to store our map values into vector - so we have to use back_inserter on our vector: back_inserter(your_values_vector). The back_inserter is special outputIterator that pushes new elements at the end of given (as paremeter) collection.
The last parameter is unaryOperation - it takes only one parameter - inputIterator's value. So we can use lambda:
[](auto &kv) { [...] }, where &kv is just a reference to map item's pair. So if we want to return only values of map's items we can simply return kv.second:
[](auto &kv) { return kv.second; }
I think this explains any doubts.
If you are using the boost libraries, you can use boost::bind to access the second value of the pair as follows:
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <boost/bind.hpp>
int main()
{
typedef std::map<std::string, int> MapT;
typedef std::vector<int> VecT;
MapT map;
VecT vec;
map["one"] = 1;
map["two"] = 2;
map["three"] = 3;
map["four"] = 4;
map["five"] = 5;
std::transform( map.begin(), map.end(),
std::back_inserter(vec),
boost::bind(&MapT::value_type::second,_1) );
}
This solution is based on a post from Michael Goldshteyn on the boost mailing list.
Using lambdas one can perform the following:
{
std::map<std::string,int> m;
std::vector<int> v;
v.reserve(m.size());
std::for_each(m.begin(),m.end(),
[&v](const std::map<std::string,int>::value_type& p)
{ v.push_back(p.second); });
}
Here is what I would do.
Also I would use a template function to make the construction of select2nd easier.
#include <map>
#include <vector>
#include <algorithm>
#include <memory>
#include <string>
/*
* A class to extract the second part of a pair
*/
template<typename T>
struct select2nd
{
typename T::second_type operator()(T const& value) const
{return value.second;}
};
/*
* A utility template function to make the use of select2nd easy.
* Pass a map and it automatically creates a select2nd that utilizes the
* value type. This works nicely as the template functions can deduce the
* template parameters based on the function parameters.
*/
template<typename T>
select2nd<typename T::value_type> make_select2nd(T const& m)
{
return select2nd<typename T::value_type>();
}
int main()
{
std::map<int,std::string> m;
std::vector<std::string> v;
/*
* Please note: You must use std::back_inserter()
* As transform assumes the second range is as large as the first.
* Alternatively you could pre-populate the vector.
*
* Use make_select2nd() to make the function look nice.
* Alternatively you could use:
* select2nd<std::map<int,std::string>::value_type>()
*/
std::transform(m.begin(),m.end(),
std::back_inserter(v),
make_select2nd(m)
);
}
One way is to use functor:
template <class T1, class T2>
class CopyMapToVec
{
public:
CopyMapToVec(std::vector<T2>& aVec): mVec(aVec){}
bool operator () (const std::pair<T1,T2>& mapVal) const
{
mVec.push_back(mapVal.second);
return true;
}
private:
std::vector<T2>& mVec;
};
int main()
{
std::map<std::string, int> myMap;
myMap["test1"] = 1;
myMap["test2"] = 2;
std::vector<int> myVector;
//reserve the memory for vector
myVector.reserve(myMap.size());
//create the functor
CopyMapToVec<std::string, int> aConverter(myVector);
//call the functor
std::for_each(myMap.begin(), myMap.end(), aConverter);
}
Why not:
template<typename K, typename V>
std::vector<V> MapValuesAsVector(const std::map<K, V>& map)
{
std::vector<V> vec;
vec.reserve(map.size());
std::for_each(std::begin(map), std::end(map),
[&vec] (const std::map<K, V>::value_type& entry)
{
vec.push_back(entry.second);
});
return vec;
}
usage:
auto vec = MapValuesAsVector(anymap);
I thought it should be
std::transform( map.begin(), map.end(),
std::back_inserter(vec),
boost::bind(&MapT::value_type::first,_1) );
We should use the transform function from STL algorithm, the last parameter of transform function could be a function object, function pointer or a lambda function that convert item of map to item of vector. This case map have items have type pair that need to convert to item that has int type for vector. Here is my solution that I use lambda function:
#include <algorithm> // for std::transform
#include <iterator> // for back_inserted
// Map of pair <int, string> need to convert to vector of string
std::map<int, std::string> mapExp = { {1, "first"}, {2, "second"}, {3, "third"}, {4,"fourth"} };
// vector of string to store the value type of map
std::vector<std::string> vValue;
// Convert function
std::transform(mapExp.begin(), mapExp.end(), std::back_inserter(vValue),
[](const std::pair<int, string> &mapItem)
{
return mapItem.second;
});
The other answers mention std::transform, and semantically it's the right choice. But in practice std::accumulate might fit better for this task, because:
it allows adding const to the resulting vector;
it just looks nicer, truly functional-style.
Example (using C++17 syntax):
#include <numeric> // for std::accumulate. Note that it's not in <algorithm> where std::transform is located, thanks to Anton Krug for pointing this out
auto map = std::map<int,bool>{};
map[0]=true;
map[1]=false;
const auto mapValues = std::accumulate(map.begin(), map.end(), std::vector<bool>(map.size()), [](auto& vector, const auto& mapEntry) {
vector.push_back(mapEntry.second);
return vector;
});
Surprised nobody has mentioned the most obvious solution, use the std::vector constructor.
template<typename K, typename V>
std::vector<std::pair<K,V>> mapToVector(const std::unordered_map<K,V> &map)
{
return std::vector<std::pair<K,V>>(map.begin(), map.end());
}