如何在C++中按照对象的某些字段获取向量中的最小或最大元素?

7

(这个问题与我的情况有所不同,让我对自己的理解产生了怀疑。)

我有这个类:

class MyOwnClass
{ 
public:
    int score; Specialcustomtype val1; double index;
private:

};

和一个MyOwnClass的向量

vector<MyOwnClass> MySuperVector(20);

我有一些代码,用于为MyOwnClass的字段设置值,我想找出在向量中哪个MyOwnClass的字段分数具有最高值。

在相关问题的答案中:

#include <algorithm> // For std::minmax_element
#include <tuple> // For std::tie
#include <vector> // For std::vector
#include <iterator> // For global begin() and end()

struct Size {
    int width, height;
};

std::vector<Size> sizes = { {4, 1}, {2, 3}, {1, 2} };

decltype(sizes)::iterator minEl, maxEl;
std::tie(minEl, maxEl) = std::minmax_element(begin(sizes), end(sizes),
    [] (Size const& s1, Size const& s2)
    {
        return s1.width < s2.width;
    });

但在我的情况下,MyOwnClass的字段类型不同,我的尝试使用“max_elements”失败了。

当然,我可以循环遍历向量的n个元素,并使用比较来找到得分最高的对象,这样做确实有效,但我相信c++的内置函数比我的版本更有效率。


“你指的是MyOwnClass的字段类型不同是什么意思?” - NaCl
我的意思是score是一个整数,val1是Specialcustomtype类型(一种虚构的类型),而index是一个双精度浮点数。我只想考虑score字段。 - Doombot
1
那么为什么不重载 operator<() 并仅检查 score 呢? - David G
1
@Doombot - 我不太明白为什么你不能拿你发布的示例,然后将其调整为查找最低分数。这实际上是一个复制/粘贴的解决方案。只需用你的向量替换原来的向量,并将要比较的字段替换为你想要比较的字段即可。 - PaulMcKenzie
是的,那就是我所做的,但是不知何故,“::iterator”关键字出现了问题。与此相反,莫斯科的Vlad版本可以正常工作。 - Doombot
3个回答

18

请尝试以下方法

std::vector<MyOwnClass> MySuperVector(20);

//..filling the vector

auto max = std::max_element( MySuperVector.begin(), MySuperVector.end(),
                             []( const MyOwnClass &a, const MyOwnClass &b )
                             {
                                 return a.score < b.score;
                             } ); 

如果您需要同时查找最小值和最大值,则可以使用标准算法std::minmax_element。它返回一对迭代器,第一个指向第一个最小元素,第二个指向最后一个最大元素。否则,您需要分别调用std::max_elementstd::min_element。如果您需要获取第一个最小值和第一个最大值或最后一个最小值和最后一个最大值。

另一种方法是为每个可用于查找最大值或最小值的字段定义内部函数对象。例如:

class MyOwnClass
{ 
public:
    int score; Specialcustomtype val1; double index;

    struct ByScore
    {
        bool operator ()( const MyOwnClass &a, const MyOwnClass &b ) const
        { 
            return a.score < b.score;
        }
    };

    struct ByIndex
    {
        bool operator ()( const MyOwnClass &a, const MyOwnClass &b ) const
        { 
            return a.index < b.index;
        }
    };
private:

};

//...

auto max_score = std::max_element( MySuperVector.begin(), MySuperVector.end(),
                                   MyOwnClass::ByScore() ); 

auto max_index = std::max_element( MySuperVector.begin(), MySuperVector.end(),
                                   MyOwnClass::ByIndex() ); 

请注意,如果score是一个昂贵的计算函数而不是一个简单的公共成员变量,那么最好自己循环以最小化调用次数。否则,例如,MySuperVector[0].score()可能会被多次调用(将元素0与元素1进行比较,现在将元素0与元素2进行比较)。 - dlf
我没有最初询问,但假设没有“索引”字段,我想知道向量中具有最大分数字段的对象是哪个,你会怎么做?我目前正在尝试使用std::distance。 - Doombot
好的,我使用了:int hihihihi = distance(MySupervector.begin(), max); cout << "Index = " << hihihihi << endl;它有效了。谢谢 Vlad! :) - Doombot

5
无论元素的类型如何不同,您始终可以比较您感兴趣的字段:
std::vector<MyOwnClass> MySuperVector(20);

// A pred function to adjust according to your score
bool comparator(const MyOwnClass& s1, const MyOwnClass& s2) {
    return s1.score < s2.score;
}

int main() {
    MySuperVector[0].score = 23; // This will be returned
    MySuperVector[1].score = 2;
    MySuperVector[5].score = -22;

    auto element = std::max_element(MySuperVector.begin(), 
                                    MySuperVector.end(), comparator);

    std::cout << element->score; // 23
}

示例

请注意,您甚至不需要使用minmax_element函数,因为您只需要查找最大元素(max_element更适合)。

如果运行时效率对于查找最大值很重要,您可能需要查看priority_queues适配器)。


-2
class test
{
private:
int num;
public:
test()
{
    num = 0;

}
test(int n)
{
    num = n;
}
void get(test ob1,test ob2)
{
    if (ob1.num > ob2.num)
    {
        cout << "Max Object nu is:" << ob1.num << endl;
    }
    else
    {
        cout << "Max Object number is:" << ob2.num << endl;
    }
}

};
void main()
{
test a(6);
test b(4);
test c;
c.get(a,b);
system("pause");
}    

请在回答中添加一些描述。@Mian Moaz - Rohit Poudel
哎呀!这个答案对应的问题是什么? - Johannes Overmann

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