Как отсортировать вектор пар на основе второго элемента пары?
Если у меня есть вектор пар:
std::vector<std::pair<int, int> > vec;
Есть ли и простой способ сортировки списка в порядке возрастания на основе второго элемента пары?
Я знаю, что могу написать небольшой объект функции, который будет выполнять эту работу, но есть ли способ использовать существующие части STL и std::less
для выполнения работы напрямую?
EDIT: Я понимаю, что я могу написать отдельную функцию или класс, чтобы перейти к третьему аргументу для сортировки. Вопрос в том, могу ли я построить его из стандартных материалов. Я бы действительно выглядел так:
std::sort(vec.begin(), vec.end(), std::something_magic<int, int, std::less>());
Ответы
Ответ 1
Вы можете использовать boost следующим образом:
std::sort(a.begin(), a.end(),
boost::bind(&std::pair<int, int>::second, _1) <
boost::bind(&std::pair<int, int>::second, _2));
Я не знаю стандартного способа сделать это в равной степени коротким и кратким, но вы можете захватить boost::bind
все, состоящее из заголовков.
Ответ 2
EDIT: используя С++ 14, лучшее решение очень легко написать благодаря lambdas, который теперь может иметь параметры типа auto
. Это мое текущее любимое решение
std::sort(v.begin(), v.end(), [](auto &left, auto &right) {
return left.second < right.second;
});
Просто используйте пользовательский компаратор (это необязательный третий аргумент std::sort
)
struct sort_pred {
bool operator()(const std::pair<int,int> &left, const std::pair<int,int> &right) {
return left.second < right.second;
}
};
std::sort(v.begin(), v.end(), sort_pred());
Если вы используете компилятор С++ 11, вы можете написать то же самое с помощью lambdas:
std::sort(v.begin(), v.end(), [](const std::pair<int,int> &left, const std::pair<int,int> &right) {
return left.second < right.second;
});
РЕДАКТИРОВАТЬ: в ответ на ваши изменения на ваш вопрос, вот некоторые мысли...
если вы действительно хотите быть творческим и сможете многократно использовать эту концепцию, просто создайте шаблон:
template <class T1, class T2, class Pred = std::less<T2> >
struct sort_pair_second {
bool operator()(const std::pair<T1,T2>&left, const std::pair<T1,T2>&right) {
Pred p;
return p(left.second, right.second);
}
};
вы также можете сделать это:
std::sort(v.begin(), v.end(), sort_pair_second<int, int>());
или даже
std::sort(v.begin(), v.end(), sort_pair_second<int, int, std::greater<int> >());
Хотя, честно говоря, все это немного переборщило, просто напишите 3-строчную функцию и сделайте с ней: -P
Ответ 3
С С++ 0x мы можем использовать лямбда-функции:
using namespace std;
vector<pair<int, int>> v;
.
.
sort(v.begin(), v.end(),
[](const pair<int, int>& lhs, const pair<int, int>& rhs) {
return lhs.second < rhs.second; } );
В этом примере неявно выводится тип возврата bool
.
Типы возврата Lambda
Когда лямбда-функция имеет один оператор, и это оператор return, компилятор может выводить возвращаемый тип. Из С++ 11, §5.1.2/4:
...
- Если составной оператор имеет вид
{ return expression ; }
тип возвращаемого выражения после преобразования lvalue-to-rvalue (4.1), преобразования между массивами и указателями (4.2) и преобразования функции в указатель ( 4.3); - в противном случае
void
.
Чтобы явно указать тип возврата, используйте форму []() -> Type { }
, например:
sort(v.begin(), v.end(),
[](const pair<int, int>& lhs, const pair<int, int>& rhs) -> bool {
if (lhs.second == 0)
return true;
return lhs.second < rhs.second; } );
Ответ 4
Его довольно простой
вы используете функцию сортировки из алгоритма и добавляете свою собственную функцию сравнения
vector< pair<int,int > > v;
sort(v.begin(),v.end(),myComparison);
Теперь вам нужно сделать сравнение на основе второго выбора
поэтому объявите вас "myComparison" как
bool myComparison(const pair<int,int> &a,const pair<int,int> &b)
{
return a.second<b.second;
}
Ответ 5
Для чего-то многоразового использования:
template<template <typename> class P = std::less >
struct compare_pair_second {
template<class T1, class T2> bool operator()(const std::pair<T1, T2>& left, const std::pair<T1, T2>& right) {
return P<T2>()(left.second, right.second);
}
};
Вы можете использовать его как
std::sort(foo.begin(), foo.end(), compare_pair_second<>());
или
std::sort(foo.begin(), foo.end(), compare_pair_second<std::less>());
Ответ 6
Вам придется полагаться на нестандартный select2nd
Ответ 7
Попробуйте поменять элементы пар, чтобы вы могли использовать std::sort()
как обычно.