Как отсортировать вектор STL?

Я хотел бы отсортировать vector

vector<myClass> object;

Где myclass содержит множество int переменные. Как я могу отсортировать vector по любой конкретной переменной данных myClass

67 голосов | спросил NativeCoder 3 Maypm10 2010, 16:48:12

5 ответов


0

Перегрузите меньше, чем оператор, затем сортируйте. Это пример, который я нашел в Интернете ...

class MyData
{
public:
  int m_iData;
  string m_strSomeOtherData;
  bool operator<(const MyData &rhs) const { return m_iData < rhs.m_iData; }
};

std::sort(myvector.begin(), myvector.end());

Источник: здесь

ответил Gabe 3 Maypm10 2010, 16:51:21
0
std::sort(object.begin(), object.end(), pred());

где pred() - это функциональный объект, определяющий порядок объектов myclass. Кроме того, вы можете определить myclass::operator<.

Например, вы можете передать лямбду:

std::sort(object.begin(), object.end(),
          [] (myclass const& a, myclass const& b) { return a.v < b.v; });

Или, если вы застряли в C ++ 03, подход функционального объекта (v - это элемент, для которого вы хотите вид):

struct pred {
    bool operator()(myclass const & a, myclass const & b) const {
        return a.v < b.v;
    }
};
ответил avakar 3 Maypm10 2010, 16:50:40
0

Указатель на член позволяет вам написать один компаратор, который может работать с любым членом данных вашего класса:

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

template <typename T, typename U>
struct CompareByMember {
    // This is a pointer-to-member, it represents a member of class T
    // The data member has type U
    U T::*field;
    CompareByMember(U T::*f) : field(f) {}
    bool operator()(const T &lhs, const T &rhs) {
        return lhs.*field < rhs.*field;
    }
};

struct Test {
    int a;
    int b;
    std::string c;
    Test(int a, int b, std::string c) : a(a), b(b), c(c) {}
};

// for convenience, this just lets us print out a Test object
std::ostream &operator<<(std::ostream &o, const Test &t) {
    return o << t.c;
}

int main() {
    std::vector<Test> vec;
    vec.push_back(Test(1, 10, "y"));
    vec.push_back(Test(2, 9, "x"));

    // sort on the string field
    std::sort(vec.begin(), vec.end(), 
        CompareByMember<Test,std::string>(&Test::c));
    std::cout << "sorted by string field, c: ";
    std::cout << vec[0] << " " << vec[1] << "\n";

    // sort on the first integer field
    std::sort(vec.begin(), vec.end(), 
        CompareByMember<Test,int>(&Test::a));
    std::cout << "sorted by integer field, a: ";
    std::cout << vec[0] << " " << vec[1] << "\n";

    // sort on the second integer field
    std::sort(vec.begin(), vec.end(), 
        CompareByMember<Test,int>(&Test::b));
    std::cout << "sorted by integer field, b: ";
    std::cout << vec[0] << " " << vec[1] << "\n";
}

Вывод:

sorted by string field, c: x y
sorted by integer field, a: y x
sorted by integer field, b: x y
ответил Steve Jessop 3 Maypm10 2010, 17:11:54
0

Как объяснено в других ответах, вам нужно предоставить функцию сравнения. Если вы хотите, чтобы определение этой функции было близко к sort вызов (например, если это имеет смысл только для этого вида), вы можете определить его прямо здесь с boost::lambda. Используйте boost::lambda::bind для вызова функции-члена.

Например, сортировать по переменной-члену или функции data1:

#include <algorithm>
#include <vector>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
using boost::lambda::bind;
using boost::lambda::_1;
using boost::lambda::_2;

std::vector<myclass> object(10000);
std::sort(object.begin(), object.end(),
    bind(&myclass::data1, _1) < bind(&myclass::data1, _2));
ответил Benjamin Bannier 3 Maypm10 2010, 17:29:15
0

это мой подход, чтобы решить это вообще. Он расширяет ответ от Стива Джессопа, удаляя требование явно задавать аргументы шаблона и добавляя возможность также использовать функтоин и указатели на методы (получатели)

#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
#include <functional>

using namespace std;

template <typename T, typename U>
struct CompareByGetter {
    U (T::*getter)() const;
    CompareByGetter(U (T::*getter)() const) : getter(getter) {};
    bool operator()(const T &lhs, const T &rhs) {
        (lhs.*getter)() < (rhs.*getter)();
    }
};

template <typename T, typename U>
CompareByGetter<T,U> by(U (T::*getter)() const) {
    return CompareByGetter<T,U>(getter);
}

//// sort_by
template <typename T, typename U>
struct CompareByMember {
    U T::*field;
    CompareByMember(U T::*f) : field(f) {}
    bool operator()(const T &lhs, const T &rhs) {
        return lhs.*field < rhs.*field;
    }
};

template <typename T, typename U>
CompareByMember<T,U> by(U T::*f) {
    return CompareByMember<T,U>(f);
}

template <typename T, typename U>
struct CompareByFunction {
    function<U(T)> f;
    CompareByFunction(function<U(T)> f) : f(f) {}
    bool operator()(const T& a, const T& b) const {
        return f(a) < f(b);
    }
};

template <typename T, typename U>
CompareByFunction<T,U> by(function<U(T)> f) {
    CompareByFunction<T,U> cmp{f};
    return cmp;
}

struct mystruct {
    double x,y,z;
    string name;
    double length() const {
        return sqrt( x*x + y*y + z*z );
    }
};

ostream& operator<< (ostream& os, const mystruct& ms) {
    return os << "{ " << ms.x << ", " << ms.y << ", " << ms.z << ", " << ms.name << " len: " << ms.length() << "}";
}

template <class T>
ostream& operator<< (ostream& os, std::vector<T> v) {
    os << "[";
    for (auto it = begin(v); it != end(v); ++it) {
        if ( it != begin(v) ) {
            os << " ";
        }
        os << *it;
    }
    os << "]";
    return os;
}

void sorting() {
    vector<mystruct> vec1 = { {1,1,0,"a"}, {0,1,2,"b"}, {-1,-5,0,"c"}, {0,0,0,"d"} };

    function<string(const mystruct&)> f = [](const mystruct& v){return v.name;};

    cout << "unsorted  " << vec1 << endl;
    sort(begin(vec1), end(vec1), by(&mystruct::x) );
    cout << "sort_by x " << vec1 << endl;
    sort(begin(vec1), end(vec1), by(&mystruct::length));
    cout << "sort_by len " << vec1 << endl;
    sort(begin(vec1), end(vec1), by(f) );
    cout << "sort_by name " << vec1 << endl;
}
ответил Arne 22 J0000006Europe/Moscow 2014, 23:21:28

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132