C++ 2D vector - Convert int to double - c++

What is a good way to convert vector<vector<int>> vint to vector<vector<double>>vdouble?
I know from C++ convert vector<int> to vector<double> that this can be done for 1-D but I am not too sure how to do it for 2-d case.

Here's a pretty simple solution which uses emplace_back and the vector range constructor:
std::vector<std::vector<int>> intvec;
//intvec filled somehow
std::vector<std::vector<double>> doublevec;
doublevec.reserve(intvec.size());
for (auto&& v : intvec) doublevec.emplace_back(std::begin(v), std::end(v));

#include <iostream>
#include <vector>
#include <algorithm>
double castToDouble(int v) {
return static_cast<double>(v);
}
int main() {
std::vector<std::vector<int>> intv;
std::vector<std::vector<double>> doublev;
std::transform(intv.begin(), intv.end(), std::back_inserter(doublev), [](const std::vector<int> &iv) {
std::vector<double> dv;
std::transform(iv.begin(), iv.end(), std::back_inserter(dv), &castToDouble);
return dv;
});
return 0;
}

The naive solution is to use two loops, one nested inside the other, preferably range-based for loops.
You could also use e.g. std::transform with a lambda expression that in turn also calls std::transform on the nested vector, which does the actual conversion.
If you use std::transform remember to set the size of the destination vector, or use e.g. std::back_inserter.

A simple way is with std::transform and the range constructor of std::vector. If you're using back_inserter, you should reserve() some capacity to avoid repeated reallocations.
Live example: http://coliru.stacked-crooked.com/a/84ef0e3d6572792a
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<std::vector<int>> vvi = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
std::vector<std::vector<double>> vvd;
vvd.reserve(vvi.size());
std::transform(begin(vvi), end(vvi), std::back_inserter(vvd),
[](const std::vector<int>& vi) {
return std::vector<double>(begin(vi), end(vi));
});
// Output the destination container for verification:
for_each(begin(vvd), end(vvd), [](const std::vector<double>& vd){
std::copy(begin(vd), end(vd), std::ostream_iterator<double>(std::cout, " "));
std::cout << "\n";});
}

Related

How do I copy the strings in a vector<pair<string, int>> to vector<string>?

I'm using GCC 9.2.0 and boost 1.55.
I have 2 vectors:
vector< pair< string, int > > source;
vector< string > dest;
I need to transform the source vector to the dest, such that it should contain only string elements of source vector.
Is it possible using boost::push_back and adaptors?
boost::range::push_back( dest, source | /* adaptor ??? */ );
Currently I have this workable code, but it should be changed:
transform( source.begin(), source.end(), back_inserter(dest), __gnu_cxx::select1st< std::pair< std::string, int > >() );
To continue the trend of posting mimimal improvements:
Live On Compiler Explorer
#include <boost/range/adaptor/map.hpp>
#include <fmt/ranges.h>
using namespace std::string_literals;
using namespace boost::adaptors;
template <typename R>
auto to_vector(R const& range) {
return std::vector(boost::begin(range), boost::end(range));
}
int main() {
std::vector source {std::pair {"one"s,1},{"two",2},{"three",3}};
fmt::print("keys {}\nvalues {}\n",
source | map_keys,
source | map_values);
// if you really need the vectors
auto keys = to_vector(source | map_keys);
auto values = to_vector(source | map_values);
}
Prints
keys {"one", "two", "three"}
values {1, 2, 3}
You could use std::transform and std::back_inserter with a lambda instead:
#include <algorithm> // transform
#include <iterator> // back_inserter
std::transform(source.begin(), source.end(), std::back_inserter(dest),
[](auto& p) {
return p.first;
});
Here's a boost solution with the transformed adaptor:
#include <boost/range/adaptor/transformed.hpp>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
using boost::adaptors::transformed;
// define function object (so we can pass it around) emulating std::get
template<std::size_t N>
auto constexpr get = [](auto const& x){ return std::get<N>(x); };
int main()
{
// prepare sample input
std::vector<std::pair<std::string,int>> source{{"one",1},{"two",2},{"three",3}};
// the line you look for
auto dest = source | transformed(get<0>);
// dest is a vector on which we can iterate
for (auto const& i : dest) {
std::cout << i << '\n';
}
// if you really need it to be a vector
auto dest_vec = boost::copy_range<std::vector<std::string>>(dest);
}
Here's a solution using the range-v3 library:
auto dest = source
| ranges::views::keys
| ranges::to<std::vector<std::string>>;
Here's a demo.
In C++20, there's no std::ranges::to, but you can still copy over the keys to dest if it already exists:
std::ranges::copy(source | std::views::keys,
std::back_inserter(dest));
Here's a demo.
Note that this doesn't work in Clang trunk, which I assume is a bug.

How to deduce template parameter funct for for_each

I am trying to remove entries from an unordered_map. A vector holds the keys that need to be removed from the unordered_map. I am trying to use for_each to iterate through the vector and call erase on the unordered_map.
#include <unordered_map>
#include <vector>
#include<algorithm>
int main()
{
std::unordered_map<int, bool> sample_map = { {0, false}, {1, true}, {2,false}};
std::vector keys_to_delete = { 0, 2};
std::for_each(keys_to_delete.begin(), keys_to_delete.end(), &sample_map.erase);
}
I receive the error:
note: couldn't deduce template parameter '_Funct' std::for_each(keys_to_delete.begin(), keys_to_delete.end(), &sample_map.erase);
How do I correctly bind sample_map's erase function?
You're missing a template argument for the vector key_to_delete.
Anyways, this problem might be simpler if you manually wrote the code that looped through each key and called the function erase.
However, if you'd like to use std::for_each then you could bind it to the correct function to be called. In this case, one has to static_cast to get the correct function since erase has multiple overloads.
#include <unordered_map>
#include <vector>
#include<algorithm>
#include <functional>
#include <iostream>
int main()
{
std::unordered_map<int, bool> sample_map = { { 0, false },{ 1, true },{ 2,false } };
std::vector<int> keys_to_delete = { 0, 2 };
using type = std::unordered_map<int, bool>;
std::for_each(keys_to_delete.begin(), keys_to_delete.end(), std::bind(static_cast<std::size_t(type::*)(const int&)>(&type::erase), &sample_map, std::placeholders::_1));
}
The way to do what you want is to use a lambda like so:
std::for_each(keys_to_delete.begin(), keys_to_delete.end(), [&](const auto& key) { sample_map.erase(key); });
std::for_each is not quite suitable there. The code would be cleaner with for.
#include <unordered_map>
#include <vector>
#include<algorithm>
int main()
{
std::unordered_map<int, bool> sample_map = { {0, false}, {1, true}, {2,false}};
std::vector<int> keys_to_delete = { 0, 2};
for (auto key : keys_to_delete)
sample_map.erase(key);
}
With using for_each the code will be heavy for understanding. std::unordered_map::erase has overloads, thus it can not be used directly, you would have to create a functional object that calls suitable overloaded method, or use lambda.

How to operate on two vectors and save the result to another vector [duplicate]

This question already has answers here:
How to add element by element of two STL vectors?
(6 answers)
Closed 8 years ago.
vector<int> vecIntsA{1, 2, 3, 4};
vector<int> vecIntsB{5, 6, 7, 8};
vector<int> vecIntsC(vecIntsA.size(), 0);
for(vector<int>::size_type i = 0; i < vecIntsA.size(); ++i)
{
vecIntsC[i] = vecIntsA[i] + vecIntsB[i];
}
Question> Is there a STL algorithm that can be used to make this calculation be done in one line?
#include <algorithm>
#include <functional>
#include <vector>
std::vector<int> vecIntsA{1, 2, 3, 4};
std::vector<int> vecIntsB{5, 6, 7, 8};
std::vector<int> vecIntsC( vecIntsA.size(), 0)
std::transform( vecIntsA.begin(), vecIntsA.end(),
vecIntsB.begin(), vecIntsC.begin(), op);
where op is binary operation, std::plus<int>() or a custom summation function like:
int sumInt( const int& a, const int& b)
{
return a + b;
}
With C++14, you can even drop any explicit mention of the type and use just std::plus<>():
std::transform( vecIntsA.begin(), vecIntsA.end(),
vecIntsB.begin(), vecIntsC.begin(), std::plus<>());
#include <algorithm>
#include <functional>
std::transform(vecInstA.begin(), vecInstA.end(),
vecInstB.begin(), vecInstC.begin(), std::plus<int>());

Iterable union of two vectors

I have two arrays, as follows:
std::array<int,6> A,B;
//Fill A with random data
//File B with random data
For whatever reason, I'd like some kind of container object which lets me access both of the vectors individually, but also to iterate over their union, allowing for actions such as follows:
union_container uc(A,B);
for(unioned::iterator i=uc.begin();i!=uc.end();++i)
*i+=1;
uc.first()[2]=4;
uc.second()[4]=5;
I could code this unioned class myself, but perhaps there is already a library which allows this?
Using Boost zip iterators is one way to do this.
#include <array>
#include <functional>
#include <iostream>
#include <boost/tuple/tuple.hpp>
#include <boost/iterator/zip_iterator.hpp>
template<typename T>
using ZipIt = boost::zip_iterator< boost::tuple<T*, T*> >;
template<typename T>
using ZipRef = decltype(*ZipIt<T>());
template<typename T>
void operator+=(ZipRef<T> z, T const& v)
{
z.template get<0>() += v;
z.template get<1>() += v;
}
int main()
{
std::array<int, 6> a = { 1, 3, 5, 7, 9, 11 };
std::array<int, 6> b = { 2, 4, 6, 8, 10, 12 };
std::for_each(
boost::make_zip_iterator(boost::make_tuple(std::begin(a), std::begin(b))),
boost::make_zip_iterator(boost::make_tuple(std::end(a), std::end(b))),
[](ZipRef<int> z){ z += 1; }
);
std::copy(std::begin(a), std::end(a), std::ostream_iterator<int>(std::cout, ",")); std::cout << "\n";
std::copy(std::begin(b), std::end(b), std::ostream_iterator<int>(std::cout, ",")); std::cout << "\n";
a[2] = 4;
b[4] = 5;
}
Online output.
Note that the code above is not as general as I've would liked, since the jump to variadic templates and general iterator types proved a bit hairy (left as an exercise!) This has mainly to do with the fact that boost::zip_iterator uses some tricky internal facades around boost::tuple. For this reason I also used decltype in the template alias for ZipRef to avoid having to write such nasty types inside the std::for_each lambda expression.

How do I use for_each to output to cout?

Is there a more straight-forward way to do this?
for_each(v_Numbers.begin(), v_Numbers.end(), bind1st(operator<<, cout));
Without an explicit for loop, if possible.
EDIT:
How to do this for std::cin with a std::vector if possible? (How to read n elements only)?
You could achieve this using std::copy into a std::ostream_iterator:
std::vector<int> v_Numbers; // suppose this is the type
// put numbers in
std::copy(v_Numbers.begin(), v_Numbers.end(),
std::ostream_iterator<int>(std::cout));
It would be even nicer if you add some suffix:
std::copy(v_Numbers.begin(), v_Numbers.end(),
std::ostream_iterator<int>(std::cout, "\n"));
This assumes that your container is a vector<int>, so you will have to replace that part with the appropriate type.
Edit regarding reading input:
Conversely, you can copy from a range of std::istream_iterator into a vector using std::back_inserter:
std::vector<int> v_Numbers;
std::copy(std::istream_iterator<int>(std::cin), std::istream_iterator<int>(),
std::back_inserter(v_Numbers));
If you want to read n elements only, look at this question.
Another option — Boost.Lambda.
for_each(v.begin(), v.end(), cout << boost::lambda::_1);
Yep, but you must use std::copy algorithm:
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> a;
// fill a...
std::copy(a.begin(), a.end(), std::ostream_iterator<int>(std::cout));
}
yup, using lambda expression (C++ 11) we can inline printing of each element of a STL container to cout.
#include <iostream> // cout
#include <vector> // vector
#include <algorithm> // for_each
#include <iterator> // istream_iterator
using namespace std;
int main()
{
std::vector<int> v(10,2);
std::for_each(v.begin(), v.end(), [](int i)->void {std::cout << i <<endl;});
return 0;
}
For reading "n" values from cin to vector,
int main()
{
std::vector<int> v;
int elementsToRead;
cin>>elementsToRead; // Number of elements to copy
// Reading from istream
std::istream_iterator<int> ii2(std::cin);
std::copy_n(ii2, elementsToRead, std::back_inserter(v));
// printing updated vector
std::for_each(v.begin(), v.end(), [](int i)->void {cout << i <<endl;});
return 0;
}
(or) by using Lambda expression
std::for_each(std::istream_iterator<int>(cin),std::istream_iterator<int>(),[&v](int i)->void { v.push_back(i);});
To know more about Lambda expression # What is a lambda expression in C++11?
Not always appropriate in corporate code, but for the sake of enumerating options - if you really find other for_each / std::copy etc. solutions too verbose, you could write:
std::ostream& operator(std::ostream& os, const std::vector<My_Type>& v)
{
// pick one of the other implementations for here...
std::copy(std::istream_iterator<My_Type>(os), std::istream_iterator<My_Type>(),
std::back_inserter(v_Numbers));
}
It's much nicer if you're well-mannered (;-p) enough to only overload your specific instantiation of vector (which requires My_Type be more than a typedef to say int, though it's not hard to create a templated class to create new types wrapping an arbitrary type). Otherwise, if someone else does the same elsewhere in your translation unit, the streaming could become ambiguous.
I know the copy with the iterator is the optimal solution, but just to answer with for_each.
You could do:
#include <vector>
#include <algorithm>
#include <locale>
int main() {
using namespace std;
locale::global(locale(""));
wcout::imbue(locale());
vector<int> vec{1000,2000,3000,4000,5000};
for_each(vec.begin(), vec.end(), [](auto &x){wcout << x << endl;});
return 0;
}
But, for me, it's REALLY much more readable the simple for ...
#include <vector>
#include <locale>
int main() {
using namespace std;
locale::global(locale(""));
wcout::imbue(locale());
vector<int> vec{1000,2000,3000,4000,5000};
for(auto &v: vec) {
wcout << v << endl;
}
return 0;
}