find_if 的两个条件

Posted

技术标签:

【中文标题】find_if 的两个条件【英文标题】:Two conditions for find_if 【发布时间】:2013-07-17 21:07:08 【问题描述】:

std::vector<unsigned int> 中,我想找到小于某个数字的最大数字的元素的位置。例如:

v = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

我想找一个最大小于 8 的数。那个数是 7。

以下代码不正确,但这可能是我想要得到的。

std::vector<unsigned int>::iterator pnt = std::find_if (v.begin(), v.end(), [](const unsigned int& x)  return x < 8; && x == MAX; );

【问题讨论】:

你能缩进你的第二行吗,它不可见。 你的数组并不总是排序的,对吧?还是这样? @jrok:是的,总是排序的。 然后调用 std::lower_bound() 进行二分查找;这个“小细节”改变了一切。 【参考方案1】:

如果你的向量总是排序的,那么你可以用对数复杂度来做

auto it = std::lower_bound(v.begin(), v.end(), 8); // first value >= 8
auto m = *((it != v.begin())? --it : it);         

如果您的向量未排序,但可以修改,您可以分两步完成:

auto it = std::partition(v.begin(), v.end(), [](int x)  x < 8 );
auto m = *(it != v.begin())? std::max_element(v.begin(), it) : it);

如果你不能修改你的向量,你可以手动修改

auto max = 0;
for (elem: v) 
   if (elem < 8) 
       m = std::max(elem, m);

// m is now the max of all elements < 8

这两种最终方法都具有线性复杂性。后者可以通过使用 Boost.Iterator 库中的 filter_iterator 来概括,但是您已经深入到模板领域,所以只有在您反复需要这种魔法时才这样做。

【讨论】:

在第一种方法中,x &lt; 8会被选中,因为有7个小于8的数字。 @Shibli 我不明白你的评论:std::partition 会将每个 >= 8 的元素交换到返回的迭代器的最右边。 当向量 v 8, 9, 10 受到您刚刚提出的方式的影响时,您不会遇到问题,因为没有值适用,后一种方法将返回'0' 的值不正确。 @hetepeperfan 是的,我想我可以为这种边缘情况稍微“强化”代码,尽管对于空范围,std::max_element 返回v.begin()【参考方案2】:

我会创建一个函数来检查向量内是否有任何值,如果没有则抛出错误。然后我会保存低于遇到的最大值但高于当前找到的最大值的每个值。这就是我将如何实现它的方式。

unsigned smaller_than ( const std::vector<unsigned int>& v, unsigned max) 

    bool intial_found = false;
    unsigned largest;
    unsigned i;
    for ( i = 0; i < v.size() ;++i)
        if ( v [i] < max )
            largest = v[i];
            intial_found = true;
            break;
        
    
    if ( ! intial_found ) 
        throw "oops";/*of course you make a Nice std::exception for this case*/
    
    for (  ; i < v.size(); i++ ) 
        if ( v[i] < max && v [i] > largest)
            largest = v[i];
        
    
    return largest;

【讨论】:

如果没有找到答案,则从搜索例程中抛出,被认为是反模式:在搜索的上下文中,未能找到答案不是错误(不导致不变量或帖子失败) - 或前置条件)参见 Alexandrescu & Sutter 的 C++ 编码标准第 72 条。

以上是关于find_if 的两个条件的主要内容,如果未能解决你的问题,请参考以下文章

使用std::find_if提取序列容器的子串

如何使用find_if查找类的匹配对象? (或任何其他方式来实现结果)

地图上的 find_if 问题

在 find_if 中使用谓词

为啥 std::find_if(first, last, p) 不采用引用谓词?

find_if 中具有多个参数的 Lambda