如何使用用户定义的谓词查找向量的最大元素

Posted

技术标签:

【中文标题】如何使用用户定义的谓词查找向量的最大元素【英文标题】:How to find max element of a vector with user defined predicate 【发布时间】:2019-07-18 11:07:54 【问题描述】:

我需要找到向量的最大元素。我想使用 STL 库中的 max_element。

我试过的代码是:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class A

public:
    A(int _size, long _len) : size(_size), len(_len)

    int size;
    long len;
;

bool CompareMaxA(const A& _a, const A& _b)

    return _a.len > _b.len;


int main() 

    vector<A> vec;
    A a1(3, 10);
    A a2(5, 30);
    vec.push_back(a1);
    vec.push_back(a2);

    auto it = max_element(vec.begin(), vec.end(), CompareMaxA);

    cout << "max = " << it->len;

    return 0;

我得到的是 max = 10,而不是 max = 30。为什么?

【问题讨论】:

因为max_element() 假定谓词确定是否_a &lt; _b。由于您的谓词返回_a &gt; b,因此您指定最大值和最小值的角色是相反的。 【参考方案1】:

你的比较函数做错了。只要_a.len 大于 大于_b.len,它就会返回true,但std::max_element 需要一个自定义比较函数,该函数在完全相反的情况下返回true。来自std::max_element上的cppreference:

参数

[...]

comp - 比较函数对象(即满足比较要求的对象),如果第一个参数小于第二个参数,则返回真。

你可以修复它

bool lessThanByLen(const A& _a, const A& _b)

    return _a.len < _b.len;


auto it = max_element(vec.begin(), vec.end(), lessThanByLen);

由标准库使用/传递给订单关系的自定义比较器总是寻找小于关系。在这种情况下,算法名称 (max_element) 表示应找到最大值。

请注意,正如 @JeJo 在 cmets 中指出的那样,您也可以考虑传递一个 lambda:

auto it = max_element(vec.begin(), vec.end(),
    [](const A& lhs, const A& rhs)  return lhs.len < rhs.len; );

【讨论】:

【参考方案2】:

在 STL 中,谓词应该检查较少的关系(即,如果 LHS 小于 RHS)。如果您的自定义谓词实现更大的运算符,结果将相反(例如 max->min)。

解决方法是将CompareMaxA中的&gt;替换为&lt;

【讨论】:

【参考方案3】:

这个比较

bool CompareMaxA(const A& _a, const A& _b)

    return _a.len > _b.len;

如果第一个参数大于第二个参数,则返回 true。

标准算法std::max_element使用以下条件

comp( max_value, current_value )

如果返回值为true,则current_value 变为max_value

您的比较函数永远不会返回 true,因为 10 总是小于 30。

如果某些current_element 小于最初被视为当前最大值的第一个元素,它将返回true

所以你的函数搜索向量中的最小元素。

要找到最大元素,您必须反转条件。

bool CompareMaxA(const A& _a, const A& _b)

    return _a.len < _b.len;

对应于标准函数对象std::less

考虑以下演示程序

#include <iostream>
#include <functional>
#include <iterator>
#include <algorithm>

/*
//How the algorithm can look

template <class ForwardIterator, class Compare>
ForwardIterator max_element( ForwardIterator first, ForwardIterator last, Compare comp )

    auto max_element = first;

    if ( first != last )
    
        while ( ++first != last )
        
            if ( comp( *max_element, *first ) ) max_element = first;
        
    

    return max_element;

*/

int main( void )

    int a[] =  1, 2, 3, 4, 5 ;

    auto it = max_element( std::begin( a ), std::end( a ), std::less<>() );

    std::cout << *it << '\n';

    // this corresponds to your comparison function
    it = max_element( std::begin( a ), std::end( a ), std::greater<>() );

    std::cout << *it << '\n';

它的输出是

5
1

即使用算法std::max_element 与类似于标准函数对象std::less 的比较函数给出最大值。

将算法 std::max_element 与类似于标准函数对象 std::greater 的比较函数一起使用,可以得出最小值。

反之亦然

将算法 std::min_element 与类似于标准函数对象 std::less 的比较函数一起使用,可以得出最小值。

并使用算法std::min_element 与类似于标准函数对象std::greater 的比较函数给出最大值。

【讨论】:

以上是关于如何使用用户定义的谓词查找向量的最大元素的主要内容,如果未能解决你的问题,请参考以下文章

如何根据 R 中的用户定义层次结构找到向量的最大字符?

如何对向量使用查找算法

查找向量的向量的最大值/最小值

向量。如何设置最大元素数并找到当前计数?

如何使用 find_if 在给定的对向量中查找元素

使用自定义谓词对 numpy 数组进行排序