【问题标题】:Sort vector of structs by a variable within the struct? [duplicate]通过结构中的变量对结构向量进行排序? [复制]
【发布时间】:2013-09-16 14:00:00
【问题描述】:

我有一个数据结构,例如:

struct Data
{
string firstname;
string lastname:
string age;
}

我已将每个结构放在一个向量 (VectorOfData) 中。是否可以遍历该向量并按年龄递减对向量中的每个结构进行排序?使用类似的东西:

for(std::vector<Data>::const_iterator it = VectorOfData.begin(); it != VectorOfData.end(); ++it)
{

//sorting by age here?

}

我假设它不会那么简单,因为 it 迭代器一次只访问向量中的一个结构?

我意识到我什至可以在将结构放入向量之前进行排序,但我的问题并不是那么简单。这只是我能解释的最简单的方法。任何建议将不胜感激,谢谢

【问题讨论】:

  • 你可以使用operator&lt;std::sort from &lt;algorithm&gt;
  • “我猜它不会那么简单”?你有 STL,而且它更简单
  • @sinsedrix 谢谢。这真的很简单。跑了 3 小时睡眠,变得懒惰
  • 附带说明:使用单个 for 循环对项目集合进行排序,理论上是不可能的,顺便说一句。因为,在一般情况下,使用基于比较的排序算法,您不可能优于 Θ(n*log(n))。

标签: c++


【解决方案1】:

您可以将 std::sort 与自定义比较函数一起使用:

bool is_younger(const Data& x, const Data& y) { return x.age < y.age; }

排序:

std::sort(VectorOfData.begin(), VectorOfData.end(), is_younger);

或者,您可以定义一个自定义 functor(注意:这实际上是首选,因为它增加了内联的可能性,请阅读:更快的排序

struct is_younger_functor
{
    bool operator()(const Data& x, const Data& y) const
    {
        return x.age < y.age; 
    }
};

排序:

std::sort(VectorOfData.begin(), VectorOfData.end(), is_younger_functor());

如果您想为Data 定义严格的排序关系,您应该考虑将其转换为常规类型(定义运算符、>=)。

在这种情况下,您不需要定义这个 is_younger 函子,并且可以仅使用迭代器调用 std::sort。

编辑:严格来说,您只需要为 std::sort 定义运算符

【讨论】:

  • 注意:您需要定义的唯一运算符是operator &lt;(const Data&amp; rhs),如果这是您采取的路线。 stdlib 需要严格的弱排序,并且 all 其他操作符都可以从那个操作符中设计出来。
  • 我知道(据我所知,Alexander Stepanov 在实施 STL 时非常小心,以确保不需要其他运算符)。他还不止一次表示,如果您确实定义了&lt; 运算符,那么您还应该定义其他运算符。
  • 我同意应该准确地定义它们。它们可以(并且应该)严格按照operator &lt; 的评估来定义。我真的很喜欢这种设计方法,尽管它有时会令不少没有立即掌握的工程师感到头疼,可以肯定的是。 (和 +1,顺便说一句)
  • @utnapistim 谢谢。这是我用 C++ 做过的最简单的事情。哈
  • @utnapistim,为什么我们需要 const 指针?我们不会修改它,对吧?
【解决方案2】:

您可以使用std::sort。它在算法中定义为

template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );

其中comp是类型的比较函数

bool cmp(const Type1 &a, const Type2 &b);

您可以根据自己的需要进行定义。

如果你有 C++11,可以传入一个 lambda 函数。例如

std::sort(VectorOfData.begin(), VectorOfData.end(), [](const Data &a, const Data &b)
{
    return (a.age.length() < b.age.length());
});

如果你不能使用 C++11,你可以在某处声明和定义比较器函数,然后你甚至不需要将它传递给排序。这也适用于 C++11。

bool operator<(const Data& a, const Data& b)
{
    return (a.age.length() < b.age.length());
}

std::sort(VectorOfData.begin(), VectorOfData.end());  // sort's variant without comparator

我推荐第二种声明operator&lt; 的方法,因为为类定义比较器函数更有意义; lambda 方式更像是一种写入和丢弃类型的便利函数。

【讨论】:

  • 我很欣赏教育。我接受了另一个答案,因为我首先使用它,但这也会派上用场
  • @GeorgeCostanza:没问题 :)
  • 对于这个具体的例子,我觉得推荐第二种方法不行;它只会按年龄对类进行排序,名字和姓氏将被完全忽略,如果您希望对所有内容进行排序,肯定会导致意外情况。如果你定义了你的操作符,它们可能会在意想不到的时候被使用(例如被编译器);不要滥用它们。
猜你喜欢
  • 2011-06-21
  • 1970-01-01
  • 2020-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多