Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Sort a vector of vector of strings with comparator. Please help me understand

Tags:

c++

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!

like image 565
user1375155 Avatar asked Dec 29 '25 18:12

user1375155


1 Answers

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
like image 67
Mr.C64 Avatar answered Jan 01 '26 09:01

Mr.C64



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!