Hi,

I would like to ask about sorting lines in C++, (4 columns = 3 columns of integers and the last one a string):

3 56 3 NA
7 50 5 NA
2 100 1 OK

I tried the function sort() using a vector of strings, but failed in cases like 120 10023, where 10023 was sorted first than 120.

Does anyone have some idea?

Cheers,

SADS

string sortPed(ofstream &myfileLog, vector<string> &vetorPed, ofstream &myfileOut)
{

	myfileLog << "\nSorting ..." << endl;
	sort(vetorPed.begin(), vetorPed.end());
	myfileLog << "SORTED! Printing ped file!" << endl;
	printV(myfileLog, vetorPed);
	printV(myfileOut, vetorPed);

}

It looks to me like you should be tokenizing the string into fields first, then using a specific field as the comparison data. std::sort() takes a third argument as a predicate, if you want to customize the comparison method:

#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main()
{
    ifstream in("test.txt");

    if (in) {
        vector<string> lines;
        string line;

        while (getline(in, line))
            lines.push_back(line);

        sort(lines.begin(), lines.end(), [](const string& a, const string& b) {
            // Use the first word for comparison
            return a.substr(0, a.find_first_of(' ')) <
                b.substr(0, b.find_first_of(' '));
        });

        for_each(lines.begin(), lines.end(), [](const string& s) { 
            cout << s << '\n'; 
        });
    }
}

Edited 5 Years Ago by Narue: n/a

Thanks for your help!

Basically, I'm not concern with the second, third and last column. The problem is just sort the first column correctly.

I will try use your code.

Cheers

The problem is just sort the first column correctly.

Convenient. That's precisely what my example does, but you need to have a C++0x friendly compiler. ;)

Hi Narue,

Thanks for your help ... You're correctly! I had problems of compilation ... :(

Do you have suggestions?

Cheers,

Do you have suggestions?

Don't use C++0x features?

#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

namespace {
    struct first_word {
        bool operator()(const string& a, const string& b)
        {
            return a.substr(0, a.find_first_of(' ')) <
                b.substr(0, b.find_first_of(' '));
        }
    };
}

int main()
{
    ifstream in("test.txt");
    vector<string> lines;
    string line;

    if (in) {
        while (getline(in, line))
            lines.push_back(line);

        sort(lines.begin(), lines.end(), first_word());

        for (vector<string>::const_iterator it = lines.begin(); it != lines.end(); ++it)
            cout << *it << '\n';
    }
}

Hi Narue,

I found the same problem:

Original file:

1005 2 3 NA
100004 1 4 NA
99 1 3 NA
909 3 5 NA
1 4 5 NA

Correct output:

1 4 5 NA
99 1 3 NA
909 3 5 NA
1005 2 3 NA
100004 1 4 NA

Output LAST CODE:
1 4 5 NA
100004 1 4 NA
1005 2 3 NA
909 3 5 NA
99 1 3 NA

This is the problem. Due the "0" in 100004, it's placed before than 1005 with lower number of "0"

That's the difference between a numeric comparison and a lexicographical comparison. Let's take 100004 and 1005 as an example. The fourth character of the former is 0 and the fourth character of the latter is 5, thus the first string is smaller because 0 is less than 5.

If you want those strings compared as numbers, then convert them to numbers.

Narue,

The problem is convert just the first column of my file. I could be created the vector of integer instead of string. Due this problem (Last column is string) I'm trying other solution.

Cheers,

This article has been dead for over six months. Start a new discussion instead.