0

I have a vector of string vectors. The second string in these vectors is what I'd like to sort by. Is there a way to do this using std::sort?

From what I can tell I should pass in a function within a struct/class but I'm not sure what it's supposed to really look like.

user3816764
  • 489
  • 5
  • 22

2 Answers2

5

Tailor your compare function so it compares the 2nd element in string vectors.

#include <algorithm>
#include <vector>
#include <string>
using std::vector;
using std::string;
bool cmp(const vector<string> &lhs, const vector<string> &rhs)
{
    return lhs[1] < rhs[1];
}

vector<vector<string> > vecvecstr;
std::sort(vecvecstr.begin(), vecvecstr.end(), cmp);

std::sort() then calls cmp() whenever a comparison for sorting is required.

If the 3rd parameter of std::sort() is omitted, it calls operator< for comparison, which compares vectors lexicographically.

timrau
  • 22,578
  • 4
  • 51
  • 64
  • So I take it that std::sort just 'knows what to do' with lhs and rhs? It automatically calls those with what is being compared? edit: Also, in the regular defualt std::sort, how is it doing this? Is it comparing all of the strings in all of the vectors or what? – user3816764 Jul 28 '14 at 02:44
  • Thank you. Why use '<' for comparison? When I use '!=' I get a segfault. Is that expected? – user3816764 Jul 28 '14 at 02:54
  • The compare function must establishes [strict weak ordering](http://en.wikipedia.org/wiki/Strict_weak_ordering#Strict_weak_orderings). – timrau Jul 28 '14 at 02:56
1

This can be a solution!

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

bool compare(const vector<string> &V1, const vector<string> &V2) {
    return V1[1] < V2[1];
}

int main(void) {
    vector< vector<string> > container;
    sort(container.begin(), container.end(), compare);
    return 0;
}

Edit

I would like to mention an alternative way in case of you don't know that(Remember, std::sort is about 670% faster than std::qsort due to the fact of inline. So this isn't better than above) :

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int compare(const void* a, const void* b) {
    vector<string> V1 = *((vector<string>*)a);
    vector<string> V2 = *((vector<string>*)b);

    if (V1[1] > V2[1])
       return -1;

    if (V1[1] == V2[1])
       return 0;

    return 1;
}

int main(void) {
    vector< vector<string> > container;
    qsort(&container[0], container.size(), sizeof(string), compare);
    return 0;
}
Kaidul
  • 15,409
  • 15
  • 81
  • 150
  • Other guy beat you to it, but thank you :) – user3816764 Jul 28 '14 at 02:51
  • 1
    Would there be any benefit to using qsort? – user3816764 Jul 28 '14 at 03:03
  • May be `sort` is better over `qsort` but some says the opposite, here you can find details http://stackoverflow.com/questions/4708105/performance-of-qsort-vs-stdsort .. I have mentioned the alternative way as someone out there may prefer to do that in second way :) – Kaidul Jul 28 '14 at 03:08
  • This post was much better before the edit. You copy the entire vectors by value every single compare – M.M Jul 28 '14 at 03:27
  • 1
    If you read the top answer to the linked question you will see that qsort was not faster – M.M Jul 28 '14 at 03:28
  • @KaidulIslamSazal For the `qsort()` variant, you should declare `V1` and `V2` as _reference_ to `vector` to avoid unnecessary object copy. – timrau Jul 28 '14 at 05:33