【问题标题】:STL algorithm to find all tuples with first element within a rangeSTL算法查找范围内第一个元素的所有元组
【发布时间】:2012-03-22 09:46:41
【问题描述】:

我有一个元组列表,该列表是根据元组的第一个元素排序的,但第二个和最后一个元素是随机顺序的。现在我想找到一个范围内第一个元素的所有元组,即返回(tuple.first>-Xtuple.first<X)的所有元组。在所有这些返回的元组中,我需要在元组的第二个元素中找到最大值和最小值。 STL 算法如何实现这一点?

【问题讨论】:

    标签: c++ stl


    【解决方案1】:
    ListType::iterator itrFirst = std::find_if( ls.begin(), ls.end(), boost::bind( &TupleType::get< 0 >, _1 ) >= rangeStart );
    ListType::iterator itrLast = std::find_if( itrFirst, ls.end(), boost::bind( &TupleType::get< 0 >, _1 ) > rangeEnd );
    for( ;itrFirst != itrLast; ++itrFirst ) // Print keys for elements in range
        std::cout << itrFirst->get<0>() << std::endl;
    

    如果你有最新的编译器(我没有),我认为 boost:: 可以替换为 std::。

    【讨论】:

    • 非常感谢。代码看起来很整洁 :) 我发现在我的代码中使用元组可能太复杂了。所以我修改它以使用 pair 代替。 [代码] 向量 > ls;向量 >::iterator itrFirst = std::find_if( ls.begin(), ls.end(), boost::bind( &pair::first, _1 ) >= -0.01);矢量 >::iterator itrLast = std::find_if( itrFirst, ls.end(), boost::bind( &pair::first, _1 ) > 0.01 ); [/code] 但它不起作用。
    • 您的编译器错误是什么?此代码需要 boost 才能工作,或者如果您有 c++98 后的编译器,您可以改为包含 并使用 std::bind。
    【解决方案2】:

    由于它已经排序,您可以使用equal_range 来获得一对划定“有趣”元组范围的迭代器:

    It const begin = std::lower_bound(list.begin(), list.end(),
                                      [X](Tuple const& t) {
                                          return t.first > -X;
                                      });
    
    It const end = std::upper_bound(begin, list.end(),
                                    [X](Tuple const& t) {
                                        return t.first < X;
                                    });
    
    std::pair<It,It> const range = std::make_range(begin, end);
    

    然后,您可以简单地迭代此范围,并注册您看到的最小值和最大值:

    int min = INT_MAX, max = INT_MIN;
    
    for (Tuple const& t: range) {
      if (t.second < min) { min = t.second; }
      if (t.second > max) { max = t.second; }
    }
    
    // min and max are correctly set
    

    所以...这不是一个单一的 STL 算法。

    注意:std::min_elementstd::max_element 确实存在,但这意味着在该范围内循环两次,但这当然是可行的。

    Tuple const& min = *std::min_element(range.first, range.second,
                           [](Tuple const& left, Tuple const& right) {
                               return left.second < right.second;
                           });
    
    Tuple const& max = *std::max_element(range.first, range.second,
                           [](Tuple const& left, Tuple const& right) {
                               return left.second < right.second;
                           });
    
    // Or as noted by Vitali, slightly more efficient:
    
    auto const minmax = std::minmax_element(range.first, range.second, 
                           [](Tuple const& left, Tuple const& right) {
                               return left.second < right.second;
                           });
    
    Tuple const& min = *minmax.first;
    Tuple const& max = *minmax.second;
    

    请注意,它给出的是一个元组,而不是 .second 成员。

    【讨论】:

    • HI Matthieu M. 第一个代码没有通过我的编译器 (VS2011)。顺便说一句,如何传递第三个参数,以便将比较函数修改为 (t.first-thirdparameter>-X) && (t.first-thirdparameter)
    • @user1285419:你是对的,相等的范围似乎并没有削减它,因为这里的范围不是按绝对值排序的。您必须改用 lower_bound 和 `upper_bound。
    • 我会使用 minmax_element 给你 O(max(floor(3/2(N−1)), 0)) 而不是 O(2N)
    • @Vitali:确实!让我修改我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-26
    • 2010-11-27
    • 1970-01-01
    • 2021-03-16
    • 2019-05-14
    • 1970-01-01
    相关资源
    最近更新 更多