按字母顺序按两个标准对向量内的结构进行排序
Sorting structures inside vector by two criteria in alphabetical order
我有以下数据结构(第一个字符串作为学校的“主题”)
map<string, vector<School>> information;
学校是:
struct School {
string name;
string location;
}
我无法按字母顺序打印出我的整个数据结构(第一个主题,然后是位置,然后是名称)。举个例子。
"map key string : struct location : struct name"
"technology : berlin : university_of_berlin"
到目前为止,我设法通过
遍历了初始地图
for (auto const key:information) {
//access to struct
vector<School> v = key.second;
//sorting by location name
//comparasion done by seperate function that returns school.location1 < school.location2
sort(v.begin(), v.end(), compare);
如果我打印出主题 (key.first) 和 v.location,它就差不多完成了。地图默认排序,位置比较有效。但我不知道如何按名称添加第二个比较。如果我再做一次排序,这次是按名称排序,那么我将丢失按位置排序的原始顺序。是否有可能在一个标准比另一个标准更重要的情况下进行“双重排序”?
可以,你只需要在compare
中添加一些条件
bool compare(School const& lhs, School const& rhs)
{
if(lhs.location != rhs.location)
return lhs.location < rhs.location)
return lhs.name < rhs.name
}
或者您可以重载 <
运算符,就像@ceorron 那样
对此有一个简单的答案,我假设您想先按 "location"
然后 "name"
。
订购
简单的方法是在struct School
结构中实现一个less运算符。
示例代码:
//in School.hpp
struct School {
string name;
string location;
bool operator<(const School& rhs) const;
}
//in School.cpp
bool School::operator<(const School& rhs) const {
if(this->location < rhs.location)
return true;
if(rhs.location < this->location)
return false;
if(this->name < rhs.name)
return true;
if(rhs.name < this->name)
return false;
return false;
}
虽然还有其他方法,您现在可以像这样调用排序。
sort(v.begin(), v.end());
我添加这个答案只是为了迂腐。请参阅 以了解此特定情况的正确内容(我会说在大多数正常情况下)。
完全可以执行多次排序。诀窍是对每个额外的传递使用 stable 排序方法。 (稳定排序保留等效元素的相对顺序。)
默认的 std::sort
算法是 Introsort — 这不是一种稳定的排序(它使用快速排序 + 插入排序,但如果快速排序需要更长的时间,则切换到堆排序)。
方便的是,标准库为我们提供了 std::stable_sort
算法,供我们在需要稳定排序时使用。
稳定排序通常比不稳定排序慢,这就是为什么我们倾向于尽可能选择不稳定排序。第一遍您可以使用不稳定排序,但您必须对所有其他遍使用稳定排序。
std::sort ( xs.begin(), xs.end(), compare_names ); // 1st pass: secondary criterion
std::stable_sort( xs.begin(), xs.end(), compare_locations ); // 2nd pass: primary criterion
最终顺序将主要按位置排序,其次按名称排序。
您可以根据需要添加任意数量的排序路径。请记住,您按照重要性的相反顺序应用通行证。例如,如果您想按(姓氏、名字、年龄)对人员进行排序,则必须按相反的顺序应用排序:年龄、名字、姓氏。
我有以下数据结构(第一个字符串作为学校的“主题”)
map<string, vector<School>> information;
学校是:
struct School {
string name;
string location;
}
我无法按字母顺序打印出我的整个数据结构(第一个主题,然后是位置,然后是名称)。举个例子。
"map key string : struct location : struct name"
"technology : berlin : university_of_berlin"
到目前为止,我设法通过
遍历了初始地图for (auto const key:information) {
//access to struct
vector<School> v = key.second;
//sorting by location name
//comparasion done by seperate function that returns school.location1 < school.location2
sort(v.begin(), v.end(), compare);
如果我打印出主题 (key.first) 和 v.location,它就差不多完成了。地图默认排序,位置比较有效。但我不知道如何按名称添加第二个比较。如果我再做一次排序,这次是按名称排序,那么我将丢失按位置排序的原始顺序。是否有可能在一个标准比另一个标准更重要的情况下进行“双重排序”?
可以,你只需要在compare
bool compare(School const& lhs, School const& rhs)
{
if(lhs.location != rhs.location)
return lhs.location < rhs.location)
return lhs.name < rhs.name
}
或者您可以重载 <
运算符,就像@ceorron 那样
对此有一个简单的答案,我假设您想先按 "location"
然后 "name"
。
简单的方法是在struct School
结构中实现一个less运算符。
示例代码:
//in School.hpp
struct School {
string name;
string location;
bool operator<(const School& rhs) const;
}
//in School.cpp
bool School::operator<(const School& rhs) const {
if(this->location < rhs.location)
return true;
if(rhs.location < this->location)
return false;
if(this->name < rhs.name)
return true;
if(rhs.name < this->name)
return false;
return false;
}
虽然还有其他方法,您现在可以像这样调用排序。
sort(v.begin(), v.end());
我添加这个答案只是为了迂腐。请参阅
完全可以执行多次排序。诀窍是对每个额外的传递使用 stable 排序方法。 (稳定排序保留等效元素的相对顺序。)
默认的 std::sort
算法是 Introsort — 这不是一种稳定的排序(它使用快速排序 + 插入排序,但如果快速排序需要更长的时间,则切换到堆排序)。
方便的是,标准库为我们提供了 std::stable_sort
算法,供我们在需要稳定排序时使用。
稳定排序通常比不稳定排序慢,这就是为什么我们倾向于尽可能选择不稳定排序。第一遍您可以使用不稳定排序,但您必须对所有其他遍使用稳定排序。
std::sort ( xs.begin(), xs.end(), compare_names ); // 1st pass: secondary criterion
std::stable_sort( xs.begin(), xs.end(), compare_locations ); // 2nd pass: primary criterion
最终顺序将主要按位置排序,其次按名称排序。
您可以根据需要添加任意数量的排序路径。请记住,您按照重要性的相反顺序应用通行证。例如,如果您想按(姓氏、名字、年龄)对人员进行排序,则必须按相反的顺序应用排序:年龄、名字、姓氏。