对结构体向量进行排序

84

我有一个vector<data> info,其中data被定义为:

struct data{
    string word;
    int number;
};

我需要按照单词字符串的长度对info进行排序。是否有一种快速简便的方法可以实现?

4个回答

115

使用比较函数:

bool compareByLength(const data &a, const data &b)
{
    return a.word.size() < b.word.size();
}

然后在头文件#include <algorithm>中使用std::sort

std::sort(info.begin(), info.end(), compareByLength);

2
如果我想按照字符串字段的字典顺序对向量进行排序,有什么方法可以处理它吗?(我正在使用C++11,如果有关系的话)。除了定义比较函数/使用lambda之外,是否有其他方法可以处理它,而是使用std::string的整数运算符<?以下是我的解决方案,使用lambda:sort(info.begin(),info.end(), [](const data& d1, const data& d2) { return (d1.word.compare(d2.word) < 0); }); - Guy Avraham

48

只需创建一个比较函数/函数对象:

bool my_cmp(const data& a, const data& b)
{
    // smallest comes first
    return a.word.size() < b.word.size();
}

std::sort(info.begin(), info.end(), my_cmp);

或者在你的data类中提供一个bool operator<(const data& a) const:

struct data {
    string word;
    int number;

    bool operator<(const data& a) const
    {
        return word.size() < a.word.size();
    }
};

或者像Fred说的那样,作为非成员:

struct data {
    string word;
    int number;
};

bool operator<(const data& a, const data& b)
{
    return a.word.size() < b.word.size();
}

只需要调用 std::sort() 函数:

std::sort(info.begin(), info.end());

为什么operator<()应该是非成员函数? - Murilo Vasconcelos
4
在我看来,你不应该使用运算符重载来包装那些不太直观的行为。在这种情况下,如果 data a 的字符串成员比 data b 短,那么说 data a "小于" data b 并没有什么意义,因此我不会使用 operator< 来表达这个想法。 - Oliver Charlesworth
已添加,但我没有看到“成员方式”存在问题。 - Murilo Vasconcelos
2
在这种情况下,我同意你的观点,这也是为什么我首先写了“函数方式”,然后再解释其他学习方法的原因。 - Murilo Vasconcelos
@MuriloVasconcelos 为什么我们需要在 operator < 中使用 const 函数? - EmptyData
显示剩余2条评论

5

是的:您可以使用自定义比较函数进行排序:

std::sort(info.begin(), info.end(), my_custom_comparison);

my_custom_comparison 需要是一个函数或者类,具有 operator() 重载(即一个函数对象),该函数接受两个 data 对象并返回一个 bool,指示第一个对象是否在第二个对象之前(即 first < second)。 或者,您可以为您的类类型 data 重载 operator<operator< 是由 std::sort 使用的默认排序方法。

无论哪种方式,比较函数都必须产生元素的严格弱序


4

正如其他人提到的那样,你可以使用比较函数,但你也可以重载<操作符,然后默认的less<T>函数也会起作用:

struct data {
    string word;
    int number;
    bool operator < (const data& rhs) const {
        return word.size() < rhs.word.size();
    }
};

然后就只需要:
std::sort(info.begin(), info.end());

编辑

正如James McNellis所指出的那样,sort默认情况下实际上不使用less<T>函数对象。然而,语句的其余部分仍然是正确的,这意味着如果您想要将struct data放入std::mapstd::set中,这仍然可以工作,但是其他提供比较函数的答案需要额外的代码才能工作。


有趣的是,虽然std::mapstd::set默认使用std::less<T>,但std::sort和其他排序函数默认使用operator<。只有在您专门指定std::less执行与operator<不同的操作时,才会注意到差异。 - James McNellis
当我说“只有当...时,你才会注意到差异”时,我是错误的。如果您有指针容器,例如std::vector<int*> v; v.insert(new int); v.insert(new int); std::sort(v.begin(), v.end());,您也会注意到差异,因为如果使用<比较不相关的指针,则行为未定义。话虽如此,我不知道为什么您想按指针值而不是所指对象的值对指针容器进行排序。 - James McNellis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接