Detecting even and odd C++ vector iterators - c++

I searched and I'm surprised this hasn't been asked yet. I know how to do it with a simple loop, how about with vector iterators?
for( std::vector<int>::iterator it = somevector.begin(); it != somevector.end(); ++it )
{
//Conditions stating a certain vector has an even or odd index.
}
Sorry for not clarifying, I meant detecting whether the index of a vector is odd or even.

This would be one simple way:
{
bool is_even = true;
for (const auto& v: somevector) {
if (is_even) even_handler(v);
else odd_handler(v);
is_even = !is_even;
}
}
Want a more complicated solution? No problem:
#include <iostream>
#include <string>
#include <utility>
#include <vector>
using std::next;
template<typename Iter, typename Func, typename...Funcs>
void RotateHandlers(Iter b, Iter e, Func f, Funcs...fs) {
if (b != e) {
f(*b);
RotateHandlers(next(b), e, fs..., f);
}
}
int main() {
std::vector<std::string> v({"Hello", "world", "it's", "really", "great", "to", "be", "here"});
RotateHandlers(v.begin(), v.end(),
[](const std::string& s){std::cout << "First|" << s << std::endl;},
[](const std::string& s){std::cout << "Then |" << s << std::endl;},
[](const std::string& s){std::cout << "And |" << s << std::endl
<< " |" << std::string(s.size(), '-') << std::endl;}
);
return 0;
}
See it here: http://ideone.com/jmlV5F

I'm going to guess you meant you wanted to detect if the current index is even or odd:
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> somevector;
somevector.push_back(1);
somevector.push_back(2);
somevector.push_back(4);
somevector.push_back(8);
somevector.push_back(111605);
for (auto it = somevector.begin(); it != somevector.end(); ++it)
{
// current index
const auto index = std::distance(somevector.begin(), it);
if ((index % 2) == 0) // even
{
std::cout << "Index " << index << " (even) is: " << *it;
}
else
{
std::cout << "Index " << index << " (odd) is: " << *it;
}
std::cout << std::endl;
}
}
You can get the distance between iterators with std::distance. (Index being distance from the start.)

If I understand the question [before its last edit] correctly, an option is:
bool is_odd(const std::vector<int> &somevector) {
for( std::vector<int>::iterator it = somevector.begin(); it != somevector.end(); ++it ) {
//Conditions stating a certain vector is even or odd.
if (*it % 2 == 0) {
return false;
}
}
return true;
}
respectively for "even vectors".

Related

Shortest solution to permute the elements of a std::vector using stl

Assume that you have an std::vector<T> of some type T and a selection of indices std::vector<int> of this vector. Now I'm looking for a function permute(const std::vector<T>& vector, const std::vector<int>& indices), that returns the permuted vector with respect to the given indices.
The problem is easily solved by writing a short function like depicted below:
template<typename T>
std::vector<T> permute(const std::vector<T>& matrix, const std::vector<int>& indices) {
std::vector<T> ret;
for (auto p : indices) {
ret.push_back(matrix[p]);
}
return ret;
}
int main(int, char**) {
std::vector<int> perm{ 1,2,0 };
std::vector<std::vector<double>> matrix = { {1.,2.,3.},{4.,5.,6.},{7.,8.,9.} };
auto matrixPerm=permute(matrix, perm);
std::cout << matrixPerm[0][0] << " == " << matrix[1][0] << std::endl;
std::cout << matrixPerm[1][0] << " == " << matrix[2][0] << std::endl;
std::cout << matrixPerm[2][0] << " == " << matrix[0][0] << std::endl;
}
I'm now wondering what might be most elegant version of this program, if we can use STL or even the Boost libraries. In STL for example we have shuffle(), but we cannot say in what way to shuffle.
Does anyone now, how to shorten the function?
Solution using std::transform()
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
int main(int, char**) {
std::vector<int> perm{ 1,2,0 };
std::vector<std::vector<double>> matrix = { {1.,2.,3.},{4.,5.,6.},{7.,8.,9.} };
std::vector<std::vector<double>> output;
std::transform(perm.begin(), perm.end(), std::back_inserter(output), [&](int i) { return matrix[i]; });
std::cout << output[0][0] << " == " << matrix[1][0] << std::endl;
std::cout << output[1][0] << " == " << matrix[2][0] << std::endl;
std::cout << output[2][0] << " == " << matrix[0][0] << std::endl;
}
You can transform the indices into iterators and then create an indirect range with Boost.Range.
#include <iostream>
#include <iterator>
#include <algorithm>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
int main(int, char**) {
using namespace boost::adaptors;
std::vector<int> perm{ 1,2,0 };
std::vector<std::vector<double>> matrix = { {1.,2.,3.},{4.,5.,6.},{7.,8.,9.} };
std::vector<std::vector<double>> output;
auto permutation = perm | transformed( [&matrix](int x) { return matrix.begin() + x; }) | indirected;
boost::copy(
permutation,
std::back_inserter(output));
std::cout << output[0][0] << " == " << matrix[1][0] << std::endl;
std::cout << output[1][0] << " == " << matrix[2][0] << std::endl;
std::cout << output[2][0] << " == " << matrix[0][0] << std::endl;
}
You could skip copying the elements and just process the range if you don't need a real vector.
The range adaptor uses the permutation iterator from the Boost.Iterator library. You can also use this directly, but you have to manually define begin and end:
auto begin = make_permutation_iterator( matrix.begin(), perm.begin() );
auto end = make_permutation_iterator( matrix.end(), perm.end() );
std::copy(begin, end, std::back_inserter(output) );

Choosing a for loop based on if condition

Condition based for loop selection.
if(valid)
for (std::multimap<int,int>::reverse_iterator rit=id_count.rbegin(); mcount<10 && rit!=id_count.rend();++rit)
else
for (std::multimap<int,int>::iterator rit=id_match.begin(); mcount<10 && rit!=id_match.end();++rit)
{
//this is common for both for loop
}
how to achieve this in C++?
You have no choice but putting the common part in a function, very roughly like this:
void somefunction(...)
{
//this is common for both for loops
}
if (valid)
{
for (std::multimap<int,int>::reverse_iterator rit=id_count.rbegin(); mcount<10 && rit!=id_count.rend();++rit)
somefunctiuon(...);
}
else
{
for (std::multimap<int,int>::iterator rit=id_match.begin(); mcount<10 && rit!=id_match.end();++rit)
somefunctiuon(...);
}
This is arguably most useful as an illustration that it's not worth combining the loop logic, though it does work. Provided here for interest value...
#include <iostream>
#include <map>
int main()
{
std::multimap<int,int> id_count = { {1,2}, {9, -2}, {1,44}, {2,3}, {3,5}, {7,34} };
for (int valid = 0; valid < 2; ++valid)
{
std::cout << "valid " << valid << '\n';
int mcount = 0;
for (std::multimap<int,int>::iterator it = valid ? id_count.rbegin().base()
: id_count.begin();
mcount<10 && (valid ? it--!=id_count.begin() : it!=id_count.end());
(valid ? it : ++it), ++mcount)
{
std::cout << "[mcount " << mcount << "] "
<< it->first << ',' << it->second << '\n';
}
std::cout << '\n';
}
}
You can create a template function:
#include <map>
#include <iostream>
template<typename I> void func(I begin, I end) {
int mcount = 0;
for (I it = begin; mcount < 10 && it != end; ++it) {
++mcount;
std::cout << "[mcount " << mcount << "] "
<< it->first << ',' << it->second << '\n';
}
}
int main() {
std::multimap<int,int> id_count = { {1,2}, {9, -2}, {1,44}, {2,3}, {3,5}, {7,34} };
for (int valid = 0; valid < 2; ++valid) {
std::cout << "valid " << valid << '\n';
if (valid) {
func(id_count.rbegin(), id_count.rend());
} else {
func(id_count.begin(), id_count.end());
}
std::cout << '\n';
}
}
But IMHO this solution is a bit complicated, so consider other ways (like placing the loop body in a function).
You can try "#if valid", like:
#if 0
for(i=1;i<10;++i)
#else
for(i=2;i<9;++i)
#endif
{
cout << i << endl;
}
In C++14 you also have an option to use generic lambdas:
auto common_code = [/* Capture state if needed */] ( auto& Iter )
{
// Your common code
};
if ( valid )
for ( std::multimap<int, int>::reverse_iterator rit = id_count.rbegin(); mcount < 10 && rit != id_count.rend(); ++rit )
common_code( rit );
else
for ( std::multimap<int, int>::iterator rit = id_match.begin(); mcount < 10 && rit != id_match.end(); ++rit )
common_code( rit );

how to subtract std::map elements from one to other and update it in C++

I am trying to subtract the 1st element of the std::map from every other element of that same std::map. I couldn't find anything about that. Is it possible? for example :
std::map<char,int> bar;
bar['a']=11; //should be deleted from other elements
bar['b']=22;
bar['c']=33;
bar['d']=44;
std::cout << "bar contains:\n";
for (std::map<char,int>::iterator it=bar.begin(); it!=bar.end(); ++it)
{
std::cout <<"key: " <<it->first << " Value=> " << it->second << '\n'; //can i delete here??
//i want to delete value of a from value of b and update the value of b
}
//the new map should be look like as follows
//bar['a']=11; //or may be 0
//bar['b']=11;
//bar['c']=22;
//bar['d']=33;
Any ideas to do it easily with map in c++?
Thanks.
C++11 Solution
You could use std::for_each for this
std::for_each(std::next(bar.begin()), bar.end(), [&bar](std::pair<const char, int>& x){ x.second -= bar.begin()->second; });
For example
#include <algorithm>
#include <iostream>
#include <iterator>
#include <map>
int main()
{
std::map<char,int> bar;
bar['a']=11;
bar['b']=22;
bar['c']=33;
bar['d']=44;
std::for_each(std::next(bar.begin()), bar.end(), [&bar](std::pair<const char, int>& x){ x.second -= bar.begin()->second; });
std::cout << "bar contains:\n";
for (std::map<char,int>::iterator it=bar.begin(); it!=bar.end(); ++it)
{
std::cout << "key: " << it->first << " Value=> " << it->second << '\n';
}
}
Output (working demo)
bar contains:
key: a Value=> 11
key: b Value=> 11
key: c Value=> 22
key: d Value=> 33
And if you want to subtract even the first element from itself, just remove the std::next call and capture the value you want to subtract out, since you're going to modify the first map entry.
auto const sub = bar.begin()->second;
std::for_each(bar.begin(), bar.end(), [&sub](std::pair<const char, int>& x){ x.second -= sub; });
C++03 Solution
To subtract the first element from everything except the first element itself
int value = bar.begin()->second;
std::map<char, int>::iterator it = bar.begin();
std::advance(it, 1);
for (; it != bar.end(); ++it)
{
it->second -= value;
}
To include the first element
int value = bar.begin()->second;
for (std::map<char, int>::iterator it = bar.begin(); it != bar.end(); ++it)
{
it->second -= value;
}
You simply need to loop over the map and subtract the value associated with the "first" key from each element, storing the result back into the same element. One approach to that is shown below:
Live example at http://coliru.stacked-crooked.com/a/1bc650592027f5f3
#include <iostream>
#include <map>
int main() {
// Set up the problem...
std::map<char, int> foo;
foo['a'] = 11;
foo['b'] = 22;
foo['c'] = 33;
foo['d'] = 44;
// Obtain the value of the 'a' key...
const int value = foo['a'];
// Subtract that value from each element...
for (auto& element : foo) {
element.second -= value;
}
// Output the map to verify the result...
for (auto& element : foo) {
std::cout << element.first << ": " << element.second << "\n";
}
return 0;
}
Note that if you loop over the entire map, you need to store the initial value of foo[a], since you'll zero it during the iterative subtraction. You can avoid this by using iterators and skipping over the first element using e.g. std::next(foo.begin()). Other answers demonstrate this technique, so I won't duplicate it here.
You can use standard algorithm std::for_each declared in header <algorithm>
If your compiler supports C++ 2014 then the code can look like
#include <iostream>
#include <map>
#include <algorithm>
#include <iterator>
int main()
{
std::map<char, int> bar;
bar['a'] = 11;
bar['b'] = 22;
bar['c'] = 33;
bar['d'] = 44;
for ( const auto &p : bar )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
if ( !bar.empty() )
{
std::for_each( std::next( bar.begin() ), bar.end(),
[value = ( *bar.begin() ).second] ( auto &p ) { p.second -= value; } );
}
for ( const auto &p : bar )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
}
The program output is
{ a, 11 } { b, 22 } { c, 33 } { d, 44 }
{ a, 11 } { b, 11 } { c, 22 } { d, 33 }
If your compiler supports only C++ 2011 then the main loop in the program can look like
if ( !bar.empty() )
{
auto value = ( *bar.begin() ).second;
std::for_each( std::next( bar.begin() ), bar.end(),
[value] ( std::pair<const char, int> &p ) { p.second -= value; } );
}
The same can be done using for example the range based for loop
#include <iostream>
#include <map>
int main()
{
std::map<char, int> bar;
bar['a'] = 11;
bar['b'] = 22;
bar['c'] = 33;
bar['d'] = 44;
for ( const auto &p : bar )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
if ( !bar.empty() )
{
auto value = ( *bar.begin() ).second;
bool first = true;
for ( auto &p : bar )
{
if ( first ) first = !first;
else p.second -= value;
}
}
for ( const auto &p : bar )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
}
Also if the element by which all other elements should be decreased is not necessary the first element of the map then you can use the following approach
#include <iostream>
#include <map>
#include <algorithm>
#include <iterator>
int main()
{
std::map<char, int> bar;
bar['a'] = 11;
bar['b'] = 22;
bar['c'] = 33;
bar['d'] = 44;
for ( const auto &p : bar )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
if ( !bar.empty() )
{
// the initializer can be any element not only the first one
const auto &value = *bar.begin();
for ( auto &p : bar )
{
if ( p.first != value.first ) p.second -= value.second;
}
}
for ( const auto &p : bar )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
}
int value = bar.begin()->second;
for(std::map<char,int>::reverse_iterator it=bar.rbegin(); it != bar.rend(); it++) {
it->second -= bar.begin()->second;
}
bar.begin()->second = value;

My range for loop doesn't work

I have to print out the size of the vector and all the contents inside it. But my for loop doesnt iterate, it doesn't go up by one but instead stays at the value 0 for the whole loop.
#include "stdafx.h"
#include <string.h>
#include <string>
#include <iostream>
#include <cctype>
#include <vector>
#include <list>
using std::string;
using std::vector;
vector<int> v2(10);
for( auto i : v2)
{
if( i == 0 )
{
std::cout << v2.size() << std::endl;
}
std::cout << "Element value " << (i) << " is " << v2[i] << std::endl;
}
So I only want to print the size once, at the start. Then print out each element value which I know will be 0 by default. But it just prints out "Element value 0 is 0" 9 times.
If you want at first to print out the size of the vector then place this output statement before the range based for statement
std::vector<int> v2(10);
std::cout << v2.size() << std::endl;
size_t i = 0;
for ( auto x : v2 )
{
std::cout << "Element value " << i++ << " is " << x << std::endl;
}
But if you are using a count then it would be better to use the ordinary for statement
std::vector<int> v2(10);
std::cout << v2.size() << std::endl;
for ( std::vector<int>::size_type i = 0; i < v2.size(); i++ )
{
std::cout << "Element value " << i << " is " << v2[i] << std::endl;
}
Your question indicates that you want to treat the first element differently. This does not work with range-based for loops out of the box. You have two options:
Use an extra variable to remember whether the first iteration was made.
Use a traditional loop, using an index variable or an iterator.
Example for 1:
bool first_iteration = true;
for( auto i : v2)
{
if (first_iteration)
{
std::cout << v2.size() << std::endl;
first_iteration = false;
}
// ...
}
Example for 2:
for (auto iter = v2.begin(); iter != v2.end(); ++iter)
{
if (iter == v2.begin())
{
std::cout << v2.size() << std::endl;
}
// ...
}

How can I display the content of a map on the console?

I have a map declared as follows:
map < string , list < string > > mapex ; list< string > li;
How can I display the items stored in the above map on the console?
Update (Back to the future): with C++11 range-based for loops –
std::map<Key, Value> m { ... /* initialize it */ ... };
for (const auto &p : m) {
std::cout << "m[" << p.first << "] = " << p.second << '\n';
}
Well it depends on how you want to display them, but you can always iterate them easily:
typedef map<string, list<string>>::const_iterator MapIterator;
for (MapIterator iter = mapex.begin(); iter != mapex.end(); iter++)
{
cout << "Key: " << iter->first << endl << "Values:" << endl;
typedef list<string>::const_iterator ListIterator;
for (ListIterator list_iter = iter->second.begin(); list_iter != iter->second.end(); list_iter++)
cout << " " << *list_iter << endl;
}
I'd try the following
void dump_list(const std::list<string>& l) {
for ( std::list<string>::const_iterator it = l.begin(); l != l.end(); l++ ) {
cout << *l << endl;
}
}
void dump_map(const std::map<string, std::list<string>>& map) {
for ( std::map<string,std::list<string>>::const_iterator it = map.begin(); it != map.end(); it++) {
cout << "Key: " << it->first << endl;
cout << "Values" << endl;
dump_list(it->second);
}
I'm a little off topic here...
I guess you want to dump the map content for debugging. I like to mention that the next gdb release (version 7.0) will have a built in python interpreter which will be used by the gcc libstdc++ to provide stl pretty printers. Here is an example for your case
#include <map>
#include <map>
#include <list>
#include <string>
using namespace std;
int main()
{
typedef map<string, list<string> > map_type;
map_type mymap;
list<string> mylist;
mylist.push_back("item 1");
mylist.push_back("item 2");
mymap["foo"] = mylist;
mymap["bar"] = mylist;
return 0; // stopped here
}
which results in
(gdb) print mymap
$1 = std::map with 2 elements = {
["bar"] = std::list = {
[0] = "item 1",
[1] = "item 2"
},
["foo"] = std::list = {
[0] = "item 1",
[1] = "item 2"
}
}
Yay!
Another form, using <algorithm>:
void printPair(const pair<string, list<string> > &p)
{
cout << "Key: " << p.first << endl;
copy(p.second.begin(), p.second.end(), ostream_iterator<string>(cout, "\n"));
}
for_each(mapex.begin(), mapex.end(), printPair);
Test program:
#include <iostream>
#include <map>
#include <list>
#include <iterator>
#include <algorithm>
using namespace std;
void printPair(const pair<string, list<string> > &p)
{
cout << "Key: " << p.first << endl;
copy(p.second.begin(), p.second.end(), ostream_iterator<string>(cout, "\n"));
}
int main()
{
map<string, list<string> > mapex;
list<string> mylist1;
mylist1.push_back("item 1");
mylist1.push_back("item 2");
mapex["foo"] = mylist1;
list<string> mylist2;
mylist2.push_back("item 3");
mylist2.push_back("item 4");
mylist2.push_back("item 5");
mapex["bar"] = mylist2;
for_each(mapex.begin(), mapex.end(), printPair);
}
You can write a quite generic overloaded function, which is good for two purposes:
It works with any map.
It allows for using <<.
The function is
template<class key_t, class value_t>
ostream& operator<<(ostream& os, const map<key_t, value_t>& m) {
for (typename map<key_t, value_t>::const_iterator it = m.begin();
it != m.end(); it++) {
os << "Key: " << it->first << ", Value: " << it->second;
}
return os;
}
cout << will work with any map for which << is defined for typenames key_t and value_t. In your case, this is not defined for value_t (= list<string>), so you also have to define it.
In a similar spirit, you can use
template<class T>
ostream& operator<<(ostream& os, const list<T>& l) {
for (typename list<T>::const_iterator it = l.begin(); it != l.end(); it++) {
os << "\"" << *it << "\", ";
}
return os;
}
So, you may:
Add these two functions.
Add the prototypes where needed.
Use using namespace std; (or add std:: as needed).
Use, e.g.,
cout << mapex << endl;
cout << li << endl;
Remember that if there is any other viable candidate for the <<s just defined (which I take there is not, otherwise you would likely not ask this question), it may take precedence over the present ones.
If you can use C++11 features, then I think range-based for loops as proposed in The Paramagnetic Croissant's answer provide the most readable option. However, if C++17 is available to you, then you can combine those loops with structured bindings to further increase readability, because you no longer need to use the first and second members. For your specific use case, my solution would look as follows:
std::map<std::string, std::list<std::string>> mapex;
mapex["a"] = { "1", "2", "3", "4" };
mapex["b"] = { "5", "6", "7" };
for (const auto &[k, v] : mapex) {
std::cout << "m[" << k.c_str() << "] =";
for (const auto &s : v)
std::cout << " " << s.c_str();
std::cout << std::endl;
}
Output:
m[a] = 1 2 3 4
m[b] = 5 6 7
Code on Coliru