Reputation: 75
i need to order a set of pairs (one is int, the second one is char), and i need to have my set ordered like this: 12 G, 11 F, 10 A, 10 B, 10 C (in descending order by first, and in ascending order by second) firstly. this is what i've tried so far, and i get some errors:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <utility>
#include <set>
using namespace std;
set <pair <int,char> > s;
bool myfunction( const pair<int, char>& i, const pair<int, char>& j ) {
if( i.first < j.first ) return false;
if( j.first < i.first ) return true;
return j.second < i.second;
}
void writes()
{ set <pair<int,char> >::iterator it;
for (it = s.begin();it<= s.end();it++) /// line (18)
cout<<(*it).second<<" "<<(*it).first<<"\n\n";
}
int main()
{ ifstream f("info.in");
int n;
f>>n;
for (int i=1;i<=n;i++)
{ pair<int,char> x;
int st;
char nd;
f>>st;
f>>nd;
x.first=st;
x.second=nd;
s.insert(x);
}
writes();
}
first error i get is at line (18) : no match for 'operator<=' (operand types are 'std::set >::.....
your help is greatly appreciated
my input file looks like this:
5
10 B
10 A
10 C
11 F
12 G
@Sam Varshavchik, thanks! that solved my problem with the errors. But still, i don't get the output i needed. I only get:
10 A
10 B
10 C
11 F
12 G
is it possible to change the order criteria in a pair ? if not, what would you recommend to use instead?
it looks like myfunction for the ordering criteria is still ignored by the program. how cand i overload it inside my pair? it looks like, it just sits there and it's never used. the program does it job regardless
i've also tried this: Using custom std::set comparator but it's still not working
using namespace std;
struct lex_compare {
bool operator()(const pair<int, char>& i, const pair<int, char>& j )
{
if( i.first != j.first )
{
return (i.first > j.first);
}
return (j.second > i.second);
}
} // forgot ";", after adding it, it works perfectly.
set <pair <int,char>, lex_compare > s; ///line (22)
void writes()
{ set <pair<int,char> >::iterator it;
for (it = s.begin();it!= s.end();it++) /// line (18)
cout<<(*it).second<<" "<<(*it).first<<"\n\n";
}
int main()
{ ifstream f("info.in");
int n;
f>>n;
for (int i=1;i<=n;i++)
{ pair<int,char> x;
int st;
char nd;
f>>st;
f>>nd;
x.first=st;
x.second=nd;
s.insert(x);
}
writes();
}
ERROR: line (22): invalid declarator before 's';
Upvotes: 3
Views: 326
Reputation: 206607
Based on
in descending order by first, and in ascending order by second
The comparison function needs to be:
bool myfunction( const pair<int, char>& i, const pair<int, char>& j )
{
if( i.first != j.first )
{
return (i.first > j.first);
}
return (j.second < i.second);
}
And then, make sure to use it when working with the set
. Instead of using
set <pair <int,char> > s;
use
set <pair <int,char>, mycompare > s;
That will require a few more changes to your program.
mycompare
before defining s
.The iterator type needs to be changed too. You have
set <pair<int,char> >::iterator it;
that needs to be:
set <pair<int,char>, mycompare >::iterator it;
If the compiler you are using supports C++11, you can use auto
also.
void writes()
{
auto it = s.begin();
for ( ; it != s.end(); it++)
{
cout<<(*it).second<<" "<<(*it).first<<"\n\n";
}
}
Upvotes: 0
Reputation: 124
In order to use custom comparators, you have to tell the container about the function/functor as described in the SO-question you linked above.
Here is a working example for your case.
#include <iostream>
#include <set>
typedef std::pair<int, char> pic_t;
struct comp {
bool operator () ( const pic_t& p1, const pic_t& p2 ) const {
return ( p1.first != p2.first ) ? ( p1.first > p2.first ) : ( p1.second < p2.second );
// identical, slightly better performance:
// return ( p1.first > p2.first ) || ( ! ( p2.first > p1.first ) && ( p1.second < p2.second ) );
}
};
int main()
{
std::set<pic_t, comp> s = { { 10, 'b' }, { 10, 'a' }, { 10, 'c' }, { 11, 'f' }, { 12, 'g' } };
for ( auto p : s )
std::cout << p.first << ", " << p.second << std::endl;
return 1;
}
Upvotes: 0
Reputation: 4553
You never call myfunction
or do anything with it!
To use it to order your set, turn myfunction
into a functor, like this:
struct comparepair {
bool operator()( const pair<int, char>& i, const pair<int, char>& j ) {
if( i.first < j.first ) return false;
if( j.first < i.first ) return true;
return i.second < j.second;
}
};
Then declare the set afterward with it as the comparator, like
set <pair <int,char>, comparepair > s;
Upvotes: 0
Reputation: 118340
for (it = s.begin();it<= s.end();it++)
Iterators, generally, do not implement less/greater-than type of comparisons. Iterators, generally, implement only ==
and !=
comparisons, tests for equality. This should be:
for (it = s.begin();it != s.end();it++)
(Only random access iterators can safely be comparison using <
and >
operators, and a std::set
s iterators are not random access iterators)
This answers the question you posed: the compilation error. This question doesn't really have anything to do with your custom set comparison function; which would be a different question.
Upvotes: 2