Как отсортировать вектор пар на основе второго элемента пары?

StackOverflow https://stackoverflow.com/questions/279854

  •  07-07-2019
  •  | 
  •  

Вопрос

Если у меня есть вектор пар:

std::vector<std::pair<int, int> > vec;

Есть ли простой способ отсортировать список в порядке возрастания на основе второго элемента пары?

Я знаю, что могу написать небольшой функциональный объект, который выполнит всю работу, но есть ли способ использовать существующие части СТЛ и std::less выполнять работу напрямую?

РЕДАКТИРОВАТЬ:Я понимаю, что могу написать отдельную функцию или класс для передачи третьему аргументу для сортировки.Вопрос в том, смогу ли я построить его из стандартных вещей.Мне действительно хотелось бы что-то вроде:

std::sort(vec.begin(), vec.end(), std::something_magic<int, int, std::less>());
Это было полезно?

Решение

РЕДАКТИРОВАТЬ : используя c ++ 14, лучшее решение очень легко написать благодаря лямбда-выражениям, которые теперь могут иметь параметры типа 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());

Если вы используете компилятор C ++ 11, вы можете написать то же самое, используя лямбда-выражения:

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> >());

Хотя, если честно, все это немного излишне, просто напишите трехстрочную функцию и покончите с этим :-P

Другие советы

Вы можете использовать повышение, как это:

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 выводится неявно.

Типы возвращаемых лямбда-выражений

Когда лямбда-функция имеет единственный оператор, и это оператор возврата, компилятор может определить тип возвращаемого значения.Из С++ 11, §5.1.2/4:

...

  • Если составное выражение имеет форму { return expression ; } тип возвращаемого выражения после преобразования lvalue в 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; } );

Это довольно просто Вы используете функцию сортировки из алгоритма и добавляете свою собственную функцию сравнения

vector< pair<int,int > > v;
sort(v.begin(),v.end(),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 () как обычно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top