C++ 如何对 STL 向量进行排序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2758080/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to sort an STL vector?
提问by NativeCoder
I would like to sort a vector
我想排序一个 vector
vector<myClass> object;
Where myclass
contains many int
variables. How can I sort my vector
on any specific data variable of myClass
.
其中myclass
包含许多int
变量。如何vector
根据myClass
.
回答by avakar
std::sort(object.begin(), object.end(), pred());
where, pred()
is a function object defining the order on objects of myclass
. Alternatively, you can define myclass::operator<
.
其中,pred()
是定义 的对象顺序的函数对象myclass
。或者,您可以定义myclass::operator<
.
For example, you can pass a lambda:
例如,您可以传递一个 lambda:
std::sort(object.begin(), object.end(),
[] (myclass const& a, myclass const& b) { return a.v < b.v; });
Or if you're stuck with C++03, the function object approach (v
is the member on which you want to sort):
或者,如果您坚持使用 C++03,则函数对象方法(v
是您要排序的成员):
struct pred {
bool operator()(myclass const & a, myclass const & b) const {
return a.v < b.v;
}
};
回答by Gabe
Overload less than operator, then sort. This is an example I found off the web...
重载小于运算符,然后排序。这是我在网上找到的一个例子......
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());
Source: here
来源:这里
回答by Steve Jessop
A pointer-to-member allows you to write a single comparator, which can work with any data member of your class:
指向成员的指针允许您编写一个比较器,它可以与您的类的任何数据成员一起使用:
#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";
}
Output:
输出:
sorted by string field, c: x y
sorted by integer field, a: y x
sorted by integer field, b: x y
回答by Benjamin Bannier
Like explained in other answers you need to provide a comparison function. If
you would like to keep the definition of that function close to the sort
call (e.g. if it only makes sense for this sort) you can define it right there
with boost::lambda
. Use boost::lambda::bind
to call the member function.
就像在其他答案中解释的那样,您需要提供比较功能。如果您想将该函数的定义保持在sort
调用附近(例如,如果它仅对此类有意义),您可以在那里使用boost::lambda
. 使用boost::lambda::bind
调用成员函数。
To e.g. sort by member variable or function data1
:
例如,按成员变量或函数排序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));
回答by Arne
this is my approach to solve this generally. It extends the answer from Steve Jessop by removing the requirement to set template arguments explicitly and adding the option to also use functoins and pointers to methods (getters)
这是我一般解决这个问题的方法。它扩展了 Steve Jessop 的答案,删除了显式设置模板参数的要求,并添加了还使用函数函数和方法指针(getter)的选项
#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;
}