C++ STL:根据另一个的内容自定义排序一个向量

pwa*_*ron 18 c++ sorting stl

这可能是最好的例子.我有两个向量/列表:

People = {Anne, Bob, Charlie, Douglas}
Ages   = {23, 28, 25, 21}
Run Code Online (Sandbox Code Playgroud)

我想根据他们的年龄使用类似的东西来对人们进行排序sort(People.begin(), People.end(), CustomComparator),但我不知道如何编写CustomComparator以查看Ages而不是People.

Jer*_*fin 27

处理此问题的常用方法是创建一个包含名称和年龄的单个向量/对象列表,而不是创建两个单独的向量/列表:

struct person { 
    std::string name;
    int age;
};
Run Code Online (Sandbox Code Playgroud)

要根据年龄进行排序,请通过一个查看年龄的比较器:

std::sort(people.begin(), people.end(), 
          [](auto const &a, auto const &b) { return a.age < b.age; });
Run Code Online (Sandbox Code Playgroud)

在较旧的C++(前C++ 11中,因此没有lambda表达式)中,您可以将比较定义为成员重载,operator<或者将其作为函数对象(重载的对象operator())进行比较:

struct by_age { 
    bool operator()(person const &a, person const &b) const noexcept { 
        return a.age < b.age;
    }
};
Run Code Online (Sandbox Code Playgroud)

然后你的排序看起来像:

std::vector<person> people;
// code to put data into people goes here.

std::sort(people.begin(), people.end(), by_age());
Run Code Online (Sandbox Code Playgroud)

至于在定义operator<类之间进行选择,或者如上所示使用单独的比较器对象,主要是对于这个类是否存在"明显"的单个排序的问题.

在我看来,分类人总是按年龄排序并不一定显而易见.但是,如果在你的程序环境中,很明显除非你明确指出,否则按年龄对人进行排序,那么实现比较是有意义的,person::operator<而不是像我一样在单独的比较类中在上面完成.

  • @ jm1234567890:不是这样.`by_age`是一个类,我们需要的是一个对象.parens意味着我们正在调用它的ctor,所以我们传递该类的一个对象来进行排序比较.但是,如果`by_age`是一个函数,那么你绝对是正确的. (2认同)

Éri*_*ant 9

正如其他人所指出的那样,你应该考虑对人和年龄进行分组.

如果你不能/不想,你可以为它们创建一个"索引",然后对该索引进行排序.例如:

// Warning: Not tested
struct CompareAge : std::binary_function<size_t, size_t, bool>
{
    CompareAge(const std::vector<unsigned int>& Ages)
    : m_Ages(Ages)
    {}

    bool operator()(size_t Lhs, size_t Rhs)const
    {
        return m_Ages[Lhs] < m_Ages[Rhs];
    }

    const std::vector<unsigned int>& m_Ages;
};

std::vector<std::string> people = ...;
std::vector<unsigned int> ages = ...;

// Initialize a vector of indices
assert(people.size() == ages.size());
std::vector<size_t> pos(people.size());
for (size_t i = 0; i != pos.size(); ++i){
    pos[i] = i;
}


// Sort the indices
std::sort(pos.begin(), pos.end(), CompareAge(ages));
Run Code Online (Sandbox Code Playgroud)

现在,第n个人的名字是people[pos[n]],它的年龄是ages[pos[n]]


lyr*_*cat 0

我建议将这两个列表合并为一个结构列表。这样你就可以operator <像 dirkgently 所说的那样简单地定义。