Iterable union of two vectors - c++

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.

Related

What does this map initialization mean in C++ STL?

int numSubarraysWithSum(vector<int>& A, int S) {
unordered_map<int, int> c({{0, 1}});// Line 1
int psum = 0, res = 0;
for (int i : A) {
psum += i;
res += c[psum - S];
c[psum]++;
}
return res;
}
What does line 1 mean? I'm confused as there are two curly braces.
It's something called an Initilizer list. According to this website:
Initializer List is used in initializing the data members of a class.
The list of members to be initialized is indicated with constructor as
a comma-separated list followed by a colon.
Basically it adds elements into your std::map (or in this case your std::unordered_map) right while you're creating it.
More specifically, from #Aconcagua comment above :
The outer braces define
the initializer list itself, the inner braces are shorthand for
constructing std::pairs, which are used in the std::map to store the keys
and corresponding values.
You can see this from this piece of code:
#include <iostream>
#include <map>
#include <unordered_map>
using namespace std;
int main()
{
map<int, int> c({{0, 1}, {1, 7}});
for (auto it = c.begin(); it!=c.end(); it++)
{
cout << it->first << " " << it->second << "\n";
}
}
Output:
0 1
1 7
There's also other data types that support this, for example std::vector :
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> test({0, 7, 9, 11, 3});
for (auto x : test) {cout << x << "\n";}
}
Output:
0
7
9
11
3
There's a lot of question regarding this:
Initializing a static std::map<int, int> in C++
What would a std::map extended initializer list look like?
And more info: https://en.cppreference.com/w/cpp/utility/initializer_list
*Cautions : As #Aconcagua mentioned below, using namespace std is not considered a good practice, although it might save some typing time.
It simply just add elements into your map. There are many different ways to do this:
unordered_map<int, int> c{ {0, 1} }; similar to your question
2 unordered_map<int, int> c;
c[0]=1;
assign key and value
3.
unordered_map<int, int> c;
c.insert(std:: make_pair (key, vale) ); use make_pair
... You can refer more here map

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 can I list-initialize my own class?

I want my own class can be list-initialized like vector:
myClass a = {1, 2, 3};
How can I do that using C++11 capabilities?
C++11 has a notion of initializer lists. To use it, add a constructor which accepts a single argument of type std::initializer_list<T>. Example:
#include <vector>
#include <initializer_list>
#include <iostream>
struct S
{
std::vector<int> v_;
S(std::initializer_list<int> l)
: v_(l)
{
std::cout << "constructed with initializer list of length " << l.size();
}
};
int main()
{
S s = { 1, 2, 3 };
return 0;
}
An initializer_list can be (like other STL containers) iterated and the size can be queried. This allows you to do as pointed in the other answer by yuyoyuppe to immediately feed it to a vector. But you may have other intents for your initialization and do something like execute an operation directly on the items of the list without copying.
#include <initializer_list>
#include <iostream>
#include <algorithm>
struct S
{
int thesum;
int items;
S(std::initializer_list<int> l) :
thesum(std::accumulate(l.begin(), l.end(), 0)),
items(l.size())
{}
};
int main()
{
S s = { 1, 2, 3 };
std::cout << s.items << std::endl;
std::cout << s.thesum << std::endl;
return 0;
}
This prints
3
6
See:
http://www.cplusplus.com/reference/initializer_list/initializer_list/?kw=initializer_list
http://en.cppreference.com/w/cpp/utility/initializer_list
-

C++ 2D vector - Convert int to double

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";});
}

How to return an iterator_range

I would like to create and hold on to an iterator_range. The range is constructed based on a predicate (for this example, I look for even numbers).
I can do this, but it seems I must make a copy elements from the underlying vector that is being iterated.
Please look for the comments marked ">>>" in the sample below.
Is there a way to create the iterator_range and NOT have to create a duplicate of entries from the original vector?
I looked, and have not seen, an answer to this particular situation.
#include <vector>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/range.hpp>
#include <boost/foreach.hpp>
#include <boost/iterator/filter_iterator.hpp>
#include <boost/range/iterator_range.hpp>
using namespace std;
using namespace boost;
typedef boost::iterator_range<vector<int>::iterator> int_range;
template< class Range, class Pred >
boost::iterator_range< boost::filter_iterator< Pred, typename boost::range_iterator<Range>::type > >
make_filter_range( Range& rng, Pred pred ) {
return boost::make_iterator_range(
boost::make_filter_iterator(pred, boost::begin(rng), boost::end(rng)),
boost::make_filter_iterator(pred, boost::end(rng), boost::end(rng)) );
}
// This is the predicate evaluation function.
bool IsEvenFilter(int val) { return val % 2 == 0; }
void TestMakeIteratorRange()
{
std::vector<int> vals;
vals.push_back(1);
vals.push_back(4);
vals.push_back(7);
vals.push_back(11);
vals.push_back(16);
vals.push_back(19);
vals.push_back(28);
//>>> The following int_range line does not compile. Why?
//>>> How can I return an int_range?
//>>> int_range intRange = make_filter_range( vals, boost::bind(&IsEvenFilter, _1));
//>>> The following WILL work, but it forces a second copy of elements from vals.
std::vector<int> v2 = boost::copy_range< std::vector<int> >(
make_filter_range( vals, boost::bind(&IsEvenFilter, _1)));
int_range intRange = int_range(v2);
// Dump out contents
BOOST_FOREACH(int &val, intRange)
{
cout << " " << val;
}
cout << endl;
}
void main()
{
TestMakeIteratorRange();
}
int_range intRange = make_filter_range( vals, boost::bind(&IsEvenFilter, _1));
You have to store the type returned by make_filter_range. Which is not int_range.
This is incidentally why auto exists (in C++11); so that you don't have to type that return value if you want to store what the function returns. If you don't have access to C++11 auto, use BOOST_AUTO instead.
If you can't use that for some reason, you can also use any_range. Which, as the name suggests, can store any range for a specific type.
Also, consider using the proper Boost range-adapters, like boost::adaptors::filtered instead of make_filter_iterator.