我想排序一个 vector
vector<myClass> object;
其中myclass
包含许多int
变量。如何vector
对的任何特定数据变量进行排序myClass
。
我想排序一个 vector
vector<myClass> object;
其中myclass
包含许多int
变量。如何vector
对的任何特定数据变量进行排序myClass
。
Answers:
重载少于运算符,然后排序。这是我在网上发现的一个例子...
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());
资料来源:这里
std::sort(object.begin(), object.end(), pred());
其中,pred()
是定义的对象顺序的函数对象myclass
。或者,您可以定义myclass::operator<
。
例如,您可以传递一个lambda:
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;
}
};
指向成员的指针使您可以编写一个比较器,该比较器可以与您的类的任何数据成员一起使用:
#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
template <typename T, typename U, U (T::*F)> struct CompareByMember2 { bool operator()(const T &lhs, const T & rhs) { return lhs.*F < rhs.*F; }};
。是否可行取决于调用方是使用变量进行成员排序,还是由不同的调用者指定不同的特定成员。
就像其他答案中解释的那样,您需要提供比较功能。如果您想使该函数的定义接近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));
这是我通常解决此问题的方法。它消除了显式设置模板参数的要求,并添加了还使用functoins和方法的指针(getter)的选项,从而扩展了Steve Jessop的答案。
#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;
}