3

I am trying to sort a vector of vector of strings but I don't understand how to create a comparator functions.

I saw this thread but could not implement into my situation: sorting vector of vector of strings in C++

so I have a vector of vector of strings looking like this:
hello, world, 1, 3, 4, 7, 2, 1
world, hello, 1, 4, 8, 4 ,2, 1
phone, mouse, 2, 3, 5, 2, 1, 4

I need to sort this vector of vector string by columns that my user specifies. My user can specify more than one column to sort. Let say column 3 and 5. Column 3(1,1,2) has same value for row 1 and 2, then we have to sort by column 5. To not complicate things, this is all by ascending order.

I don't understand the concept of how it works when you pass it to the comparator function. How does my function gets looped inside the example posted by the people in those threads?

Anyways thanks in advance!

Community
  • 1
  • 1
user1375155
  • 49
  • 2
  • 7

1 Answers1

4

You can just use std::sort to sort the vector, and define a custom comparator functor (i.e. class with overloaded operator()).

You can store the indexes of sorting columns in a std::vector (that will be part of the "state" of the custom comparator object), and compare strings from columns whose indexes are stored in that vector.

You start comparing values at column specified in the first index in the "sorting columns" vector; if they are the same, you continue comparing values at column specified in the next index in the vector, etc. This can be done inside a for loop inside the body of comparator's operator() overload.

See the following code as an example (compiled with g++ (GCC) 4.7.2):

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

vector<vector<string>> BuildTestData()
{   
    vector<string> r1 = {"hello", "world", "1", "3", "4", "7", "2", "1"};
    vector<string> r2 = {"world", "hello", "1", "4", "8", "4", "2", "1"};
    vector<string> r3 = {"phone", "mouse", "2", "3", "5", "2", "1", "4"};

    return vector<vector<string>>{r1, r2, r3};
}

void PrintData(const vector<vector<string>> & v)
{
    for (size_t r = 0; r < v.size(); r++)
    {
        for (size_t c = 0; c < v[r].size(); c++)
            cout << v[r][c] << ' ';
        cout << '\n';
    }
}

class StringListComparator
{
public:
    explicit StringListComparator(vector<int> sortColumns)
        : m_sortColumns( move(sortColumns) )
    {
    }

    bool operator()(const vector<string>& lhs, const vector<string>& rhs) const
    {   
        // For each sorting column:
        for (size_t i = 0; i < m_sortColumns.size(); i++)
        {
            // Comparison with current column
            const int currentColumn = m_sortColumns[i];

            if (lhs[currentColumn] < rhs[currentColumn])
                return true;

            if (lhs[currentColumn] > rhs[currentColumn])
                return false;

            // lhs[currentColumn] == rhs[currentColumn],
            // so check with next sorting column
        }

        return false;
    }

private:
    vector<int> m_sortColumns;
};

int main()
{
    auto v = BuildTestData();
    cout << "Before sorting:\n";    
    PrintData(v);

    vector<int> sortColumns = {5, 7}; // indexes are 0-based

    sort(v.begin(), v.end(), StringListComparator(sortColumns));

    cout << "\nAfter sort:\n";
    PrintData(v);
}

Sample run:

Before sorting:
hello world 1 3 4 7 2 1
world hello 1 4 8 4 2 1
phone mouse 2 3 5 2 1 4

After sort:
phone mouse 2 3 5 2 1 4
world hello 1 4 8 4 2 1
hello world 1 3 4 7 2 1
Mr.C64
  • 41,637
  • 14
  • 86
  • 162
  • @user1375155: Be a good StackOverflow citizen: if you find this post (and other posts written by other people) useful, please up-vote them and mark the best one as answer. – Mr.C64 Mar 04 '13 at 08:27