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 < 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 的两个条件的主要内容,如果未能解决你的问题,请参考以下文章
如何使用find_if查找类的匹配对象? (或任何其他方式来实现结果)