这可能是最好的例子。我有两个 vector/列表:
People = {Anne, Bob, Charlie, Douglas}
Ages = {23, 28, 25, 21}
我想使用 sort(People.begin(), People.end(), CustomComparator)
之类的方法根据年龄对 People 进行排序,但我不知道如何编写CustomComparator
查看年龄而不是人物。
最佳答案
明显的方法
通常的处理方法是创建一个包含姓名和年龄的对象的单个 vector/列表,而不是创建两个单独的 vector/列表:
struct person {
std::string name;
int age;
};
要根据年龄进行排序,请传递一个查看年龄的比较器:
std::sort(people.begin(), people.end(),
[](auto const &a, auto const &b) { return a.age < b.age; });
在较早的 C++(C++11 之前,因此没有 lambda 表达式)中,您可以将比较定义为 operator<
的成员重载或者作为函数对象(重载 operator()
的对象)进行比较:
struct by_age {
bool operator()(person const &a, person const &b) const noexcept {
return a.age < b.age;
}
};
那么你的排序看起来像:
std::vector<person> people;
// code to put data into people goes here.
std::sort(people.begin(), people.end(), by_age());
至于在定义 operator<
之间进行选择对于这个类,或者使用我上面显示的单独的比较器对象,这主要是一个问题,即这个类是否有一个“明显”的排序。
在我看来,按年龄对人进行分类并不一定很明显。但是,如果在您的程序上下文中很明显,除非您明确指定,否则按年龄对人进行排序,那么实现比较将是有意义的
作为 person::operator<
而不是像我上面那样在一个单独的比较类中。
其他方法
综上所述,在某些情况下,在排序之前将数据组合到结构中确实是不切实际或不可取的。
如果是这种情况,您可以考虑几个选项。如果由于您使用的 key 太昂贵而无法交换(或者根本无法交换,尽管这种情况很少见)而导致正常排序不切实际,那么您可能可以使用存储要排序的数据的类型以及与每个相关联的键集合的索引:
using Person = std::pair<int, std::string>;
std::vector<Person> people = {
{ "Anne", 0},
{ "Bob", 1},
{ "Charlie", 2},
{ "Douglas", 3}
};
std::vector<int> ages = {23, 28, 25, 21};
std::sort(people.begin(), people.end(),
[](Person const &a, person const &b) {
return Ages[a.second] < Ages[b.second];
});
您还可以很容易地创建一个单独的索引,按键的顺序排序,然后使用该索引来读取关联的值:
std::vector<std::string> people = { "Anne", "Bob", "Charlie", "Douglas" };
std::vector<int> ages = {23, 28, 25, 21};
std::vector<std::size_t> index (people.size());
std::iota(index.begin(), index.end(), 0);
std::sort(index.begin(), index.end(), [&](size_t a, size_t b) { return ages[a] < ages[b]; });
for (auto i : index) {
std::cout << people[i] << "\n";
}
但是请注意,在这种情况下,我们根本没有真正对项目本身进行排序。我们刚刚根据年龄对索引进行了排序,然后使用索引来索引我们想要排序的数据数组——但年龄和姓名都保持原来的顺序。
当然,理论上你可能会遇到这样一种奇怪的情况,上面的方法都不起作用,你需要重新实现排序才能做你真正想做的事情。虽然我认为这种可能性可能存在,但我还没有在实践中看到它(我什至不记得看到我几乎认为这是正确的做法)。
关于C++ STL : Custom sorting one vector based on contents of another,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1723066/