确定谓词是否适用于范围的无,部分或全部元素

时间:2014-09-26 10:07:31

标签: c++ algorithm

从C ++ 11开始,在算法库中我们有all_of, any_of and none_of来确定谓词是否包含范围的所有元素,任何元素或者没有元素。对这些算法之一的单个调用返回1位信息,而对于特定范围和谓词,有4种可能性:

  • 谓词适用于所有元素而不包含任何元素:范围为空;
  • 谓词适用于所有元素(并且范围不为空);
  • 谓词不包含任何元素(并且范围不为空);
  • 谓词包含一些但不是所有元素。

是否有简明有效的方法来查找此信息?调用all_of后跟none_of是可能的,但是(a)无法在单遍范围上工作,并且(b)仅在必要时准确地评估谓词。提升是可以接受的。

4 个答案:

答案 0 :(得分:10)

如果您手动检查第一个元素并根据结果选择all_ofnone_of,则可以消除(a)(b)问题。

代码(从@Angew借用enum):

enum class Result {
  empty, all, none, some
};

template <class FwIt, class Pred>
Result examine_range(FwIt from, FwIt to, Pred pred)
{
  if (from == to) return Result::empty;
  if (pred(*from)) {
    ++from;
    return all_of(from,to,pred) ? Result::all : Result::some;
  } else {
    ++from;
    return none_of(from,to,pred) ? Result::none : Result::some;
  }
}

答案 1 :(得分:1)

我是否错误地理解了这个问题,或者这是你可以通过std::accumulate做的事情?

using eana = std::tuple<bool, bool, bool, bool>;

template <typename T, typename FwdIt, typename Pred>
auto empty_all_none_any(FwdIt begin, FwdIt end, Pred predicate) -> eana {
  auto result = eana{begin == end, begin != end, begin != end, false};
  result = std::accumulate(begin, end, result, [&](eana& res, T& val) {
    if (predicate(val)) {
      std::get<2>(res) = false;
      std::get<3>(res) = true;
    }
    else {
      std::get<1>(res) = false;
    }
    return res;
  });
  return result;
}

答案 2 :(得分:0)

这是我首选的算法(来自@Angew的枚举):

enum class Result {
    empty, all, none, some
};
template<class InputIt, class UnaryPredicate>
Result examine_range(InputIt first, InputIt last, UnaryPredicate p)
{
    bool all = true, none = true;
    for (; first != last && (all || none); ++first)
        (p(*first) ? none : all) = false;
    return all ? (none ? Result::empty : Result::all)
        : (none ? Result::none : Result::some);
}

答案 3 :(得分:0)

您可以使用您描述的标准库函数执行此操作。测试任何元素是否为真,以及任何元素是否为假,然后根据此表组合结果:

             any true | none true 
            ======================
 any false |  mixed   | all false |
none false | all true |  empty    |