在c++中对对象向量进行排序

Sorting a vector of objects in C++

本文关键字:排序 向量 对象 c++      更新时间:2023-10-16

假设我有一个类"Information",它将人们的姓名和年龄存储在一个向量中。

所以…

class Information {
private:
int age;
string name;
//etc, etc...
};

我如何根据年龄以升序/降序对向量进行排序?

我相信你用的是这样的东西。

sort(listOfPeople.begin(), listOfPeople.end(), greater<Information>());

listOfPeople将作为向量。

如果希望按年龄按非降序排序,一种方法是定义一个函子进行比较:

class CompareInformations {
    public:
    // after making CompareInformations a friend class to Information...
    operator(const Information& rhs, const Information& lhs) {
        return rhs.age < lhs.age;
    }
};

然后排序:

sort(listOfPeople.begin(), listOfPeople.end(), CompareInformations());

您也可以为您的类重载operator<,而不使用比较对象:

// inside your class
bool operator <(const Information& rhs) {
    return age < rhs.age;
}

然后排序:

sort(listOfPeople.begin(), listOfPeople.end());
上面的示例假设您希望按非降序(几乎升序,但不完全是)顺序排序。要实现非升序,只需将出现的所有<更改为>

您需要创建一个比较器函数或函子类,它接受两个Information引用,如果第一个应该在第二个之前排序,则返回true

下面将从老到小排序:

bool CompareAges(const Information & left, const Information & right)
{
    return left.age > right.age;
}
std::sort(listOfPeople.begin(), listOfPeople.end(), CompareAges);

选择是升序排序还是降序排序,您可以使用不同的比较函数对sort进行两次不同的调用,或者您可以创建一个函数类,该函数类具有决定项如何排序的标志。

struct CompareAgesUpOrDown
{
    CompareAgesUpOrDown(bool bDown) : m_bDown(bDown) {}
    bool operator() (const Information & left, const Information & right)
    {
        if (m_bDown)
            return left.age < right.age;
        else
            return left.age > right.age;
    }
    bool m_bDown;
};
bool bDown = ...;
std::sort(std::sort(listOfPeople.begin(), listOfPeople.end(), CompareAgesUpOrDown(bDown));

其他人已经展示了c++ 98/03的解决方案。在c++ 11中,您可能希望使用lambda进行比较:

// ascending age:
std::sort(people.begin(), people.end(), 
          [](person const &a, person const &b) { return a.age < b.age; });
// descending age:
std::sort(people.begin(), people.end(), 
          [](person const &a, person const &b) { return b.age < a.age; });

并且,如果它碰巧发生了:

// ascending name:
std::sort(people.begin(), people.end(), 
          [](person const &a, person const &b) { return a.name < b.name; });
// descending name:
std::sort(people.begin(), people.end(), 
          [](person const &a, person const &b) { return b.name < a.name; });

IMO, Information是太通用的名字,所以我把它改成了person。相反,listOfPeople过于强调形式而不是内容(更糟糕的是,这是完全错误的,因为您实际上有一个人的向量,而不是一个列表)。在我看来,在编程中,通常最好只使用list来引用链表,而不是一般的线性数据结构。

您需要有一个比较函数或对象才能使用该排序。请查看cplusplus.com上的排序页面以获取示例和信息。

下面是使用比较函数的完整示例:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
class Information {
public:
  Information(int age, std::string name) : m_age(age), m_name(name) {}
  int age() const { return m_age; }
  std::string name() const { return m_name; }
private:
  int m_age;
  std::string m_name;
  friend bool sortInformationByAgeAscending(const Information& lhs, 
                                            const Information& rhs);      
  friend bool sortInformationByAgeDescending(const Information& lhs, 
                                             const Information& rhs);
};
bool sortInformationByAgeAscending(const Information& lhs, 
                                   const Information& rhs) {
  return lhs.m_age < rhs.m_age;
}
bool sortInformationByAgeDescending(const Information& lhs, 
                                    const Information& rhs) {
  return lhs.m_age > rhs.m_age;
}
int main (int argc, const char * argv[])
{
  std::vector<Information> info;
  info.push_back(Information(1, "Bill"));
  info.push_back(Information(5, "Ann"));
  info.push_back(Information(2, "Sue"));
  std::sort(info.begin(), info.end(), sortInformationByAgeAscending);
  std::cout << info.at(0).age() << ": " << info.at(0).name() << std::endl;
  std::cout << info.at(1).age() << ": " << info.at(1).name() << std::endl;
  std::cout << info.at(2).age() << ": " << info.at(2).name() << std::endl;
  return 0;
}

我会重载operator <,然后使用greater排序。更大本质上意味着rhs <lh。然后使用sort(listOfPeople.begin(), listOfPeople.end(), greater<Information>());>

排序

如果你决定添加operator<,你的类将很好地与std::setstd::map中的键配合,除了允许排序。

class Information {
private:
int age;
string name;
friend bool operator< (Information const& lhs, Information const& rhs){
    return lhs.age < rhs.age;
}
//etc, etc...
};

对于降序排序,必须重载>运算符而不是<然后像这样用更大的选项调用sort:sort(listOfPeople.begin(), listOfPeople.end(), greater<Information>()); xmlns:然后像这样用更大的选项调用sort="#unknown">