繁体   English   中英

`std::count_if` 的二进制谓词不起作用

[英]Binary predicate for `std::count_if` is not working

我目前正在尝试使用 lambda 函数来计算std::count_if数组中两个连续元素的总和等于一个数字。 下面给出了一个示例代码。

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

int main()
{
    const int Number = 3;
    std::vector<int> vec = {1,1,2,4,5,6};    

    auto count = std::count_if( vec.begin(), vec.end(),
    [&](int A, int B) -> bool
    {   return A+B == Number;   });

    std::cout << count << '\n';
}

输出应该是1 ,因为我们有一种可能的情况( 1 + 2 )。

然而,我没能成功。 谁能告诉我我想念什么? 这是错误消息:

|234|error: no match for call to '(main()::<lambda(int, int)>) (int&)'|

问题是std::count_if使用一元谓词。 编译器会告诉您什么:“您给了我一个带有 2 个参数的 lambda,我希望 lambda 带有一个参数”。

我相信您正在寻找的是std::adjacent_find 它比较容器的每两个相邻元素(可能使用二元谓词)。

另一种可能的选择是使用std::inner_product 首先我会写一个小辅助函数:

#include <numeric>
#include <functional>
#include <iterator>

template <typename ForwardIterator, typename BinaryPredicate>
auto count_pairs_if(ForwardIterator first, ForwardIterator last, 
                    BinaryPredicate pred)
{
    const auto n = std::distance(first, last);
    if (n < 2) return std::size_t {0};
    return std::inner_product(first, std::next(first, n - 1), std::next(first),
                              std::size_t {0}, std::plus<> {}, pred);
}

template <typename Range, typename BinaryPredicate>
auto count_pairs_if(const Range& values, BinaryPredicate pred)
{
    return count_pairs_if(std::cbegin(values), std::cend(values), pred);
}

然后你可以像这样使用它:

auto count = count_pairs_if(vec, [=] (auto lhs, auto rhs) { return lhs + rhs == Number; });

这是一个演示

正如@Yksisarvinen解释的那样, std::count_if是为一元谓词设计的。 因此编译器不能接受 lambda,我通过了。

一段时间后,我找到了另一个解决此问题的方法。 如果我提供一个模板化的函数,它需要

  1. 容器的迭代器(即开始和结束)(我需要对其进行相邻元素检查),以及
  2. 二元谓词,用于检查相邻关系

这可能是一个更自然的解决方案,就像任何其他标准算法一样。 在线观看现场演示

template <typename Iterator, typename BinaryPred = std::equal_to<>>
constexpr std::size_t count_adjacent_if(
   Iterator beginIter,
   const Iterator endIter,
   const BinaryPred pred = {})
{
   if (beginIter == endIter) return 0; // nothing to do!
   std::size_t count{};
   for (Iterator nextIter{ beginIter }; ++nextIter != endIter; beginIter = nextIter)
      if (pred(*beginIter, *nextIter))
         ++count;
   return count;
}

并且可以这样调用:

const auto count = ::count_adjacent_if(
   vec.cbegin(), vec.cend(), [number](const int lhs, const int rhs) { return lhs + rhs == number; }
);

或者像评论中提到的@bipil一样,让谓词记住前一个元素。 这是不推荐的,因为它是一个非通用的解决方案,需要非空容器。 在线观看现场演示

int lhs = vec[0];
const auto count = std::count_if(vec.cbegin() + 1, vec.cend(),
   [&](const int rhs) {
   const bool condition = (lhs + rhs == number); // check for the condition
   lhs = rhs; // change the lhs = rhs (i.e. current element = next element)
   return condition; // return the condition
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM