Как отсортировать вектор пар на основе второго элемента пары?
Если у меня есть вектор пар:
std::vector<std::pair<int, int> > vec;
есть ли и простой способ сортировки списка в порядке возрастания на основе второго элемента пары?
Я знаю, что могу написать небольшой объект функции, который будет выполнять работу, но есть ли способ использовать существующие части STL и std::less сделать работу сразу?
EDIT: я понимаю, что могу написать отдельную функцию или класс, чтобы перейти к третьему аргументу для сортировки. Вопрос могу ли я построить его из стандартных материалов. Я бы действительно что-то похожее:
std::sort(vec.begin(), vec.end(), std::something_magic<int, int, std::less>());
7 ответов:
EDIT: используя c++14, лучшее решение очень легко писать благодаря лямбдам, которые теперь могут иметь параметры типа
auto. это мое текущее любимое решениеstd::sort(v.begin(), v.end(), [](auto &left, auto &right) { return left.second < right.second; });
просто используйте пользовательский компаратор (это необязательный 3-й аргумент для
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());если вы используете компилятор C++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; });EDIT: в ответ на ваше редактирование ваш вопрос, вот некоторые мысли ... если вы действительно хочу быть творческим и иметь возможность использовать эту концепцию много, просто сделать шаблон:
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
вы можете использовать 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все это состоит из заголовков.
С C++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неявно вытекает.лямбда типы возврата
когда лямбда-функция имеет один оператор, и это оператор return, компилятор может вывести тип возвращаемого значения. От C++11, §5.1.2/4:
...
- если составной оператор имеет вид
{ return expression ; }тип возвращаемого после именующее выражение-для-правосторонним значением преобразования (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; } );
его довольно просто вы используете функцию сортировки из алгоритма и добавляете свою собственную функцию сравнения
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; }
для чего-то многоразового:
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>());
вам придется полагаться на нестандартные select2nd
попробуйте поменять местами элементы в парах, так что вы можете использовать
std::sort()как обычно.
Comments