sorting with pair

H I am trying to sort a text file either based on the first or second. So I would ask the user whether they want to sort by the first or second then it created a new txt file sorted based on what the user wants. But I can't figure out how and am having trouble with this.


input.txt

Student11 Homework
Student11 Homework
Student14 A
Student14 B-tree
Student16 Binary
Student3 Homework
Student6 Homework
Student8 B-tree
Student9 Homework
Student11 Homework
Student11 Homework
Student14 A
Student14 B-tree
Student16 Binary
Student3 Homework
Student6 Homework
Student8 B-tree
Student9 Homework
Student11 Homework
Student11 Homework
Student14 A
Student14 B-tree
Student16 Binary
Student3 Homework
Student6 Homework


Desired output txt would either sort alphabetically based on topic or the student name

This is my code so far:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ifstream in("dailylog.txt");
 ofstream output("output.txt");
 vector <pair <string,string> > v;
 string words;
 string name;

 while(getline(in,words))
 {

   v.push_back(make_pair(name,words));
 }
 in.close();
 sort(v.begin(),v.end());
 for(auto e:v){
   output<<e.second<<endl;;
 }
 output.close();



From what I have it prints the students name but the same topic
Student1 A
Student1 A
Student1 A
Student1 A
Student1 A
Student1 A
Student1 A
Student1 A
even though students a's topics should vary it doesn't change it
Last edited on
Didn't test but something like this should work:
sort(v.begin(),v.end(), [&](pair<string, string>& ref){ return ref.first.compare(ref.second) < 0});
@malibor
it does not work
Im a bit confused with that ) and semicolon would be outside the brackets?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

using PR = pair<string,string>;        // using an alias will save an awful lot of writing here ...


int main()
{
   // ifstream in( "dailylog.txt" );
   // ofstream output("output.txt");
   istringstream in( "Student11 Homework\n"
                     "Student11 Homework\n"
                     "Student14 A       \n"
                     "Student14 B-tree  \n"
                     "Student16 Binary  \n"
                     "Student3 Homework \n"
                     "Student6 Homework \n" );
   ostream &output = cout;


   vector<PR> v;
   for ( string name, words; in >> name >> words; ) v.push_back( { name, words } );

// sort( v.begin(),v.end() ,    []( PR a, PR b ) { return a.first  < b.first;  }      );   // sort on first ...
   sort( v.begin(),v.end() ,    []( PR a, PR b ) { return a.second < b.second; }      );   // ... or on second

   for( PR pr : v ) output << pr.first << "  " << pr.second << '\n';
}


Student14  A
Student14  B-tree
Student16  Binary
Student11  Homework
Student11  Homework
Student3  Homework
Student6  Homework
@lastchanve hey thanks
ifstream in( "dailylog.txt" );
ofstream output("output.txt");
can I use these in that code because its a text file that changes everytime i run the code its supposed to be a simulation and I'm trying to sort it?
I deleted my previous post, didn't test but if you want to sort on both a combination with stable partition should do the trick.

Again, I didn't test this, but a bit of modifications should give you what you want.
Note that using std::sort twice would not work because it would negate first run.

1
2
3
4
5
6
7
8
9
std::sort(v.begin(), v.end(), [&](const pair<string, string>& ref1, const pair<string, string>& ref2)
	{
		return ref1.first.compare(ref2.first) < 0;
	});

std::stable_partition(v.begin(), v.end(), [&](const pair<string, string>& ref)
	{
		return ref.first.compare(ref.second) < 0;
	});

Yes, you can go back to the filestreams - I only commented them out because you can't handle (permanent) input and output files with the online compiler.
Given the repeated values in both first and second, it looks like the comparison should probably account for both first and then second (or second and then first.)

Andy
Last edited on
@lastchance thanks very much if I were to sort descending would I switch the less than the operator to greater than?

also for when sorting it by firsts this is what it does
Student19 Homework
Student19 Sorting
Student19 Sorting
Student2 Sorting
Student2 Homework
Student2 Sorting
Student2 Sorting
Student2 B-tree
Student2 Quiz
Student2 Homework
Student2 B-tree
Student2 B-tree
Student2 B-tree
Student20 B-tree
Student20 Quiz
Student20 Sorting
Student20 Sorting
Student20 Homework
Student20 Homework
Student20 Sorting
Student20 Homework
Student20 Sorting
Student20 B-tree
Student3 Quiz
Student3 Quiz
Student3 Sorting

it sorts them together correctly but it does student 20 before 3?
Last edited on
You can indeed sort descending by switching < to >.

@andywestken is right: where the key that you are sorting on is actually equal in two pairs it would make sense to have a second-level sort as well. At this point I think I would be writing a "full" function as predicate, rather than a lambda function, because the latter seems to work best for short, simple statements.

It will put student20 before student3 because you are sorting alphabetically. If you want to do otherwise you would have to split string from numerical value. But you aren't seriously calling them Student1, Student2, etc., are you? You might just as well call them 1, 2, 3, ...

At the end of the day, write "predicate" functions to determine which of your items "come first" in the list. These functions become the third argument to std::sort().
Last edited on
Topic archived. No new replies allowed.