【问题标题】:Is there an STL/boost algorithm to check all elements in a container match a value?是否有 STL/boost 算法来检查容器中的所有元素是否匹配一个值?
【发布时间】:2011-05-12 14:54:16
【问题描述】:

是否有一个 STL/boost 算法可以测试两个迭代器之间的所有元素是否与给定值匹配?或者,谓词为所有这些都返回true

即像

template<class InputIterator, class T>
InputIterator all_match (InputIterator first, InputIterator last, const T& value)
{
    bool allMatch = true;
    while(allMatch && first!=last)
        allMatch = (value == *first++);
    return allMatch;
}

或者

template <class InputIterator, class Predicate>
bool all_true (InputIterator first, InputIterator last, Predicate pred)
{
    bool allTrue = true;
    while (allTrue && first != last) 
        allTrue = pred(*first++);
    return allTrue;
}

【问题讨论】:

    标签: c++ algorithm boost stl


    【解决方案1】:

    如果您可以否定谓词,则可以使用 std::find / std::find_if 并查看它是否返回序列的结束元素。如果不是,则返回匹配的那个。

    您可以使用 std::not1 或 std::not_equal_to 来调整函数,因此通过结合 std::find_if 您确实可以使用 STL 这样做而无需编写循环。

    bool allMatch = seq.end() == std::find_if( seq.begin(), seq.end(), 
        std::not_equal_to(val) );
    bool allPass = seq.end() == std::find_if( seq.begin(), seq.end(), 
        std::not1(pred) );
    

    【讨论】:

    • 其实我不认为not_equal_to() 语法是完全正确的。我可能做错了什么,但我不得不像这样使用bind2ndstd::find_if(seq.begin(), seq.end(), std::bind2nd(std::not_equal_to&lt;MyType&gt;(), val))
    【解决方案2】:

    C++0x 引入std::all_of

    【讨论】:

    • @avakar: Section 25.1 [algorithms.general] 它还介绍了std::any_ofstd::none_of(以及臭名昭著的std::copy_if)。
    • @avakar:我们没有使用 C++0x,但无论如何知道这很有用,谢谢。
    • 这很有趣。它表明 C++0x 向更人性化的界面转变。
    • @wilhelmtell:我不知道这是否比确定的需求更重要。 2003 年我不在该领域,所以我不能说 C++03 标准是否也适合进行这种调整。
    • @GrahamS:你并不孤单,它甚至还不是标准的,而且大多数编译器都缺乏支持,所以我们大多数“专业人士”都在工作中坚持使用 C++03。不过,这并不妨碍我们使用这些功能在家中进行实验 :)
    【解决方案3】:

    您可以使用 std:find ord std::find_if 来执行此操作。

    template <class T>
    struct pred {
        T t_;
    
        pred(const T& value) : t_(value) {}
    
        bool operator()(const T &t)
        {
            return t != t_;
        }
    };
    
    if (e.cend() == std::find_if(c.cbegin(), c.cend(), pred<T>(value)))
        print("all match value");
    

    【讨论】:

    • 据我了解, find 和 find_if 只定位容器中的第一个匹配项。我想检查迭代器之间的每个元素是否都是给定值。
    • 啊,我明白了。因此,如果元素不匹配,则定义一个为 true 的谓词,然后查看 find_if 是否到达末尾。狡猾,谢谢。 +1
    • 已经有一个谓词来测试不等于,std::not_equal_to,不用自己写了。
    • @CashCow 你是对的。这只是为了说明它是如何工作的,也许运算符 == 意义上的平等并不是 OP 所考虑的谓词。
    【解决方案4】:

    您可以将std::equal 与谓词一起使用。比如:

    using namespace std;
    using namespace boost::lambda;
    
    int main()
    {
        vector<int> a;
        a.push_back(1);
        a.push_back(1);
        a.push_back(2);
        a.push_back(2);
        a.push_back(3);
        bool allMatch = equal(a.begin(), a.begin() + 2, a.begin(), _1 == 1);
        return 0;
    }
    

    【讨论】:

      【解决方案5】:

      通常你可以数一数:

      template<class FwdIterator, class T>
      InputIterator all_match (FwdIterator first, FwdIterator last, const T& value)
      {
         return std::count(first, last, value) == std::distance(first, last);
      }
      

      当迭代器不是随机的或返回 false 时效率低下。不适用于输入迭代器。

      【讨论】:

      • 也不会在发现不匹配时立即停止,这使得它对于非常大的容器不太理想。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-15
      • 2021-09-07
      • 2010-12-29
      • 1970-01-01
      • 1970-01-01
      • 2021-07-19
      相关资源
      最近更新 更多