set_difference for a custom structure - c++

I am trying to find the difference between the following two sets:
A = {(0,0), (0,1), (1,0), (1,1), (2,2)}
B = {(0,0), (0,1), (1,0), (1,1)}
The answer I am expecting is
A - B = {(2,2)}
I tried the following code. But I am stuck unable to compile. Can anyone point out the mistake I am making?
#include <vector>
#include <algorithm>
#include <iostream>
#include <utility>
using namespace std;
class compare
{
public:
bool operator()(const pair <int, int> elem1, const pair <int, int> elem2)
{
return ((elem1.first == elem2.first) &&
(elem1.second == elem2.second));
}
};
int main()
{
vector < pair<int, int> > v, va, vb;
va.push_back(make_pair(0,0));
va.push_back(make_pair(0,1));
va.push_back(make_pair(1,0));
va.push_back(make_pair(1,1));
va.push_back(make_pair(2,2));
vb.push_back(make_pair(0,0));
vb.push_back(make_pair(0,1));
vb.push_back(make_pair(1,0));
vb.push_back(make_pair(1,1));
vector < pair<int, int> >::iterator it, result;
result = set_difference (va.begin(), va.end(),
vb.begin(), vb.end(),
inserter(v, v.end()),
compare());
// for (it = v.begin( ) ; it != result; it++)
// cout << "(" << it->first << it->second << ")" << ", ";
// cout << endl;
return 0;
}
EDIT:
The compile error message is the following:
set_difference.cc: In function `int main()':
set_difference.cc:36: error: no match for 'operator=' in 'result = std::set_difference [with _InputIterator1 = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >, _InputIterator2 = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >, _OutputIterator = std::insert_iterator<std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >, _Compare = compare]((&va)->std::vector<_Tp, _Alloc>::begin [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), (&va)->std::vector<_Tp, _Alloc>::end [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), (&vb)->std::vector<_Tp, _Alloc>::begin [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), (&vb)->std::vector<_Tp, _Alloc>::end [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), std::inserter [with _Container = std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > >, _Iterator = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >](((std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > >&)(&v)), (&v)->std::vector<_Tp, _Alloc>::end [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >]()), (compare(), compare()))'
/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stl_iterator.h:587: note: candidates are: __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >& __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >::operator=(const __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >&)

(This is addressing the correctness of the algorithms, not the compilation problems.)
Read the documentation: The two input ranges already have to be sorted.
You also have to provide an output iterator for the result.
So do this:
std::sort(va.begin(), va.end(), compare());
std::sort(vb.begin(), vb.end(), compare());
set_difference(va.begin(), va.end(), vb.begin(), vb.end(),
std::back_inserter(v), compare());
Your compare function should also define a strict, weak ordering, not an equality comparison.
By the way, std::pair<S, T> and std::tuple<T...> already come with built-in lexicographic comparison, so you shouldn't usually need to define your own comparison, unless you want something exotic: std::sort(va.begin(), va.end()); etc.

OK, now with the error message posted it's clear what is the problem:
set_difference returns the output iterator, which in this case is an insert_iterator (constructed by your call to inserter). You try to assign it to result which is a vector iterator. This is a type mismatch.
The simplest solution would be to just omit that assignment and the iterator result because you don't need that iterator anyway; the results have been written to v.

Your expectation is wrong: A - B is the set of elements in A not also found in B, which in your case is the empty set because every element in A is also found in B. B - A would give the result you expect.

Related

How to print my map<pair<int,int>, pair<int,int>> in cout

#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
int main() {
map<pair<int,int>,pair<int,int>> items;
items.insert(make_pair(1,20),make_pair(0,0));
items.insert(make_pair(2,10),make_pair(0,0));
items.insert(make_pair(3,30),make_pair(0,0));
items.insert(make_pair(4,5),make_pair(0,0));
items.insert(make_pair(5,35),make_pair(0,0));
map<pair<int,int>,pair<int,int>>::iterator it;
cout<<"Class ID:\t\t\tSamples:\t\t\tTP:\t\t\tPrecision:"<<endl;
for(it = items.begin();it!=items.end();++it)
{
cout<<(it->first).first<<"\t\t\t"<<(it->first).second<<"\t\t\t"<<(it->second).first<<"\t\t\t"<<(it->second).second<<endl;
}
}
I have a code like this but i can't print my values. Can someone help me please?
I'm getting interesting compiler error :
Here is the text of the error :
In file included from C:/PROGRA~1/MINGW-~1/X86_64~1.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/map:60,
from C:\Users\Fatih\Desktop\clion\quiz3\main.cpp:2:
C:/PROGRA~1/MINGW-~1/X86_64~1.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_tree.h: In instantiation of 'void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_II, _II) [with _InputIterator = std::pair<int, int>; _Key = std::pair<int, int>; _Val = std::pair<const std::pair<int, int>, std::pair<int, int> >; _KeyOfValue = std::_Select1st<std::pair<const std::pair<int, int>, std::pair<int, int> > >; _Compare = std::less<std::pair<int, int> >; _Alloc = std::allocator<std::pair<const std::pair<int, int>, std::pair<int, int> > >]':
C:/PROGRA~1/MINGW-~1/X86_64~1.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_map.h:893:4: required from 'void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = std::pair<int, int>; _Key = std::pair<int, int>; _Tp = std::pair<int, int>; _Compare = std::less<std::pair<int, int> >; _Alloc = std::allocator<std::pair<const std::pair<int, int>, std::pair<int, int> > >]'
C:\Users\Fatih\Desktop\clion\quiz3\main.cpp:10:48: required from here
C:/PROGRA~1/MINGW-~1/X86_64~1.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_tree.h:2467:28: error: no match for 'operator++' (operand type is 'std::pair<int, int>')
for (; __first != __last; ++__first)
^~~~~~~~~
C:/PROGRA~1/MINGW-~1/X86_64~1.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_tree.h:2468:29: error: no match for 'operator*' (operand type is 'std::pair<int, int>')
_M_insert_unique_(end(), *__first, __an);
^~~~~~~~
std::map::insert takes a parameter of value_type which is std::pair<const Key, Value>. That means you need to combine make_pair(1,20),make_pair(0,0) into a single parameter so you can call the function. That would look like
items.insert({make_pair(1,20),make_pair(0,0)});
// ^curly braces create value_type^
items.insert({make_pair(2,10),make_pair(0,0)});
items.insert({make_pair(3,30),make_pair(0,0)});
items.insert({make_pair(4,5),make_pair(0,0)});
items.insert({make_pair(5,35),make_pair(0,0)});
Alternatively you can use emplace which will take parameters to construct a value_type. That lets you get away without using the curly braces and looks like
items.emplace(make_pair(1,20),make_pair(0,0));
items.emplace(make_pair(2,10),make_pair(0,0));
items.emplace(make_pair(3,30),make_pair(0,0));
items.emplace(make_pair(4,5),make_pair(0,0));
items.emplace(make_pair(5,35),make_pair(0,0));

Trying to use find_if function to locate value in vector of pairs by first element

Have piece of code to scan large string (html) and then parse any words out of it. Push all the instances to vector or pairs (word and count) in case it's not there already, otherwise increment count (second element of pair).
vector < pair <string,int> > vect;
vector < pair <string,int> >::iterator it;
...
it = find_if (vect.begin(), vect.end(), currentword);
if (it != vect.end())
it->second++;
else
vect.push_back( make_pair(currentword, 1));
...
Getting compilation error:
In file included from C:/TDM-GCC-32/lib/gcc/mingw32/5.1.0/include/c++/bits/stl_algobase.h:71:0,
from C:/TDM-GCC-32/lib/gcc/mingw32/5.1.0/include/c++/bits/char_traits.h:39,
from C:/TDM-GCC-32/lib/gcc/mingw32/5.1.0/include/c++/ios:40,
from C:/TDM-GCC-32/lib/gcc/mingw32/5.1.0/include/c++/ostream:38,
from C:/TDM-GCC-32/lib/gcc/mingw32/5.1.0/include/c++/iostream:39,
from webCounter.cpp:19:
C:/TDM-GCC-32/lib/gcc/mingw32/5.1.0/include/c++/bits/predefined_ops.h: In instantiation of 'bool __gnu_cxx::__ops::_Iter_pred::operator()(_Iterator) [with _Iterator = __gnu_cxx::__normal_iterator, int>*, std::vector, int> > >; _Predicate = std::__cxx11::basic_string]':
C:/TDM-GCC-32/lib/gcc/mingw32/5.1.0/include/c++/bits/stl_algo.h:120:14: required from '_RandomAccessIterator std::__find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator, int>*, std::vector, int> > >; _Predicate = __gnu_cxx::__ops::_Iter_pred >]'
C:/TDM-GCC-32/lib/gcc/mingw32/5.1.0/include/c++/bits/stl_algo.h:161:23: required from '_Iterator std::__find_if(_Iterator, _Iterator, _Predicate) [with _Iterator = __gnu_cxx::__normal_iterator, int>*, std::vector, int> > >; _Predicate = __gnu_cxx::__ops::_Iter_pred >]'
C:/TDM-GCC-32/lib/gcc/mingw32/5.1.0/include/c++/bits/stl_algo.h:3815:28: required from '_IIter std::find_if(_IIter, _IIter, _Predicate) [with _IIter = __gnu_cxx::__normal_iterator, int>*, std::vector, int> > >; _Predicate = std::__cxx11::basic_string]'
webCounter.cpp:68:58: required from here
C:/TDM-GCC-32/lib/gcc/mingw32/5.1.0/include/c++/bits/predefined_ops.h:234:30: error: no match for call to '(std::__cxx11::basic_string) (std::pair, int>&)'
{ return bool(_M_pred(*__it)); }
The problem is there is no built-in comparison between a pair <string,int> and what appears to be a string. You will have to provide one. Eg.
it = find_if (vect.begin(),
vect.end(),
[currentword](const pair <string,int>& p){ // this is a lambda expression
return p.first == currentword; // compare strings
});
Documentation for Lambda Expressions
That said,
std::map<string, int> freqmap;
could be a better choice for this task if it is allowed. Just about all of the code reduces to
freqmap[currentword]++;
Documentation for std::map

How to iterate a C++ map of maps

I have a map of map
std::map< int, std::map<string, double> > myMap;
std::map< int, std::map<string, double> >::iterator itr;
Iterating it with:
itr = myMap.find(nodeI);
if (itr == myMap.end())
{
exit(1) ;
}
results in the error:
error: no match for âoperator=â in
âitr = ((const PushList*)this)->PushList::myMap.std::map&lt:_Key, _Tp, _Compare, _Alloc>::find
[with _Key = int, _Tp = std::map&lt:std::basic_string&lt:char, std::char_traits&lt:char>,
std::allocator&lt:char> >, double, std::less&lt:std::basic_string&lt:char,
std::char_traits&lt:char>,
std::allocator&lt:char> > >, std::allocator&lt:std::pair&lt:const std::basic_string&lt:char,
std::char_traits&lt:char>, std::allocator&lt:char> >, double> > >, _Compare =
std::less&lt:int>, _Alloc =
std::allocator&lt:std::pair&lt:const int, std::map&lt:std::basic_string&lt:char,
std::char_traits&lt:char>,
std::allocator&lt:char> >, double, std::less&lt:std::basic_string&lt:char,
std::char_traits&lt:char>,
std::allocator&lt:char> > >, std::allocator&lt:std::pair&lt:const std::basic_string&lt:char,
std::char_traits&lt:char>, std::allocator&lt:char> >, double> > > > >](((const
int&)((const int*)((int*)nodeI))))â
How can I iterate the map of map?
From the error you posted it can be seen that you are doing this from within a class member const function. Is there any chance that myMap happens to be a member of that class? If so, what you want is to use const_iterator instead. You should do it anyways, since you are not expecting to modify the contents of the iterated elements.

"No match for operator=" trying to iterate through map in C++

I'm trying to iterate through a map defined as the following:
std::map< size_type, std::pair<size_t, unsigned int> > ridx_;
Now I'm trying to iterate through ridx_ (which is a private member of a class) in the following friend function which overloads operator<<
std::ostream& operator<<(std::ostream &os, const SMatrix &m)
{
std::map< size_type, std::pair<size_t, unsigned int> >::iterator it;
//The following is line 34
for (it = m.ridx_.begin(); it != m.ridx_.end(); it++)
os << it->first << endl;
return os;
}
However g++ errors out with:
SMatrix.cpp:34: error: no match for 'operator=' in 'it =
m->SMatrix::ridx_.std::map<_Key, _Tp, _Compare, _Alloc>::begin with
_Key = unsigned int, _Tp = std::pair,
_Compare = std::less, _Alloc =
std::allocator > >' /usr/include/c++/4.3/bits/stl_tree.h:152: note:
candidates are: std::_Rb_tree_iterator > >&
std::_Rb_tree_iterator > >::operator=(const
std::_Rb_tree_iterator > >&) make: * [myTest] Error 1
What am I doing wrong?
Because m (and therefore m.ridx_) is const, you must use the std::map< size_type, std::pair<size_t, unsigned int> >::const_iterator, not ::iterator here.
If you're using a C++0x compiler, you might want to consider using auto as well:
for (auto it = m.ridx_.begin(); it != m.ridx_.end(); it++)

stl vector::insert difference in Windows and linux?

there. I've searched my question around here but failed to find anything relevant.
This is the problem.
I have this code in the part of my program, doing kind of stupid sort by inserts.
I developed that in MSVS 2008 and it all worked fine, but when I tried to compile that with g++, it failed because of list::insert function below;
//...
pair<uint, double> NewElem(i, Prob.at(i));
bool inserted(false);
vector<pair<uint, double> >::const_iterator li = NewList.begin();
for ( vector<double>::const_iterator ji = BlocksMemory.begin() ; ji != BlocksMemory.end() ; ++ji)
{
if (NewElem.second <= *ji)
li += _SORT_BLOCK;
else
break;
}
for(;li != NewList.end() ; ++li)
{
if (NewElem.second > li->second)
{
NewList.insert(li, NewElem );
inserted = true;
break;
}
}
as one can see, li is const_iterator of NewList;
And NewElem has type pair with the same content type as NewList contents;
There you can see the response (unreadable):
main.cpp:447: error: no matching function for call to "std::vector<std::pair<unsigned int, double>, std::allocator<std::pair<unsigned int, double> > >::insert(__gnu_cxx::__normal_iterator<const std::pair<unsigned int, double>*, std::vector<std::pair<unsigned int, double>, std::allocator<std::pair<unsigned int, double> > > >&, std::pair<unsigned int, double>&)"
/usr/include/c++/4.4/bits/vector.tcc:106: note: candidates are: __gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> > std::vector<_Tp, _Alloc>::insert(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = std::pair<unsigned int, double>, _Alloc = std::allocator<std::pair<unsigned int, double> >]
/usr/include/c++/4.4/bits/stl_vector.h:850: note: void std::vector<_Tp, _Alloc>::insert(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, size_t, const _Tp&) [with _Tp = std::pair<unsigned int, double>, _Alloc = std::allocator<std::pair<unsigned int, double> >]
What can be the reason? And what is the possible solution?
The signature of the insert member function that you are trying to use is probably:
iterator insert( iterator, const value_type& );
But the first argument that you are passing to the function is a const_iterator, that cannot be implicitly converted to a non const iterator. That code should not have worked on VS either.
The simple solution is that if you intend to modify the container you use a non-const iterator: define li as std::vector< std::pair<uint,double> >::iterator li = NewList.begin();
Also, are you sure that you want to be inserting into a std::vector? For performance reasons, a std::list would be a better choice. Also, an insert on a list doesn't invalidate existing iterators as it does for a vector.