Why does std::sort assume a std::vector< std::vector<int> > to be a std::vector by default, thereby creating wrong results?

Question

I have created a vector of vectors and I would like to sort them based on parameters that I define. Here, the sort() function takes the variable dataset defined as vector<vector<int>> to be just a vector<int>. Could someone explain what is going wrong?

Moreover, even after the above said problem is sorted out, compare() function would work only for hard coded indices. How should I go about it, if I would like to sort it based on different indices. Is there a method that I can mention to do so?

#include <iostream>
#include <vector>
#include <algorithm>

//void check_function(std::vector <std::vector <int> > *dataset)
//{
//    std::cout<<(*dataset)[0].size()<<std::endl;
//}

bool compare(const std::vector <std::vector <int> > &a, const std::vector <std::vector <int> > &b)
{
    return a[1] < b[1];
}

/* This works, but this sorts based on the first parameter of the vector rather than what I mention.
bool compare(const std::vector <int> &a, const std::vector <int> &b)
{
    return a < b;
}
*/    
int main()
{
    std::vector <int> data;
    std::vector <int> data2;
    std::vector <std::vector <int> > dataset;

    data.push_back(5);
    data.push_back(10);
    dataset.push_back(data);

    data2.push_back(5);
    data2.push_back(20);
    dataset.push_back(data2);

//    check_function(&dataset);
    std::sort(dataset.begin(), dataset.end(), compare);
    std::cout<< dataset[0][0]<<std::endl;

    return 0;
}

Show source
| sorting   | c++   | c++11   | vector   | stl   2017-01-07 22:01 1 Answers

Answers to Why does std::sort assume a std::vector&lt; std::vector&lt;int&gt; &gt; to be a std::vector by default, thereby creating wrong results? ( 1 )

  1. 2017-01-07 22:01

    Sorting a container, you need a function that compare couples of element contained in the container.

    So, sorting a std::vector<std::vector<int>>, you need a function that receive a couples of std::vector<int>.

    But your compare() receive a couple of std::vector<std::vector<int>>.

    That is wrong.

    Off Topic: your compare() function (IMHO) is very dangerous because access to the second element of both vector without checking if they contain at least two elements.

    I think you should, at least, use at() instead operator[]; just to perform a bound cecking and, in case, obtain a catchable exception; something like

    bool compare(const std::vector <int> & a, const std::vector <int> & b)
    {
        return a.at(1) < b.at(1);
    }
    

    --- EDIT ---

    The OP ask

    how do I sort it based on an index that is decided in runtime?

    Decided how? And where?

    Suppose that is decided outside compare() (in the function that call std::sort(), by example), you can use a lambda function.

    An example

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    int main()
     {
       std::vector <std::vector <int> > dataset;
    
       dataset.emplace_back(std::initializer_list<int>{200, 1});
       dataset.emplace_back(std::initializer_list<int>{5, 56});
    
       auto val = 1U;
    
       std::sort(dataset.begin(), dataset.end(),
                 [val](const std::vector <int> &a, const std::vector <int> &b)
                  { return  a.at(val) < b.at(val); });
    
       std::cout << dataset[0][0] << ", " << dataset[0][1] << std::endl;
    
       return 0;
     }
    

Leave a reply to - Why does std::sort assume a std::vector< std::vector<int> > to be a std::vector by default, thereby creating wrong results?

◀ Go back