方便的方法返回过滤集合

时间:2016-05-14 16:10:08

标签: c++ iterator iteration filtering

问题

假设我有Iterator类型的两个迭代器beginend以及一些谓词predicate(存储在obj中)。我想实现我可以编写的方法some_collection() o

for(auto element: obj.get_collection()) {
    do_smth()
}

这样它只能在满足谓词的元素上工作(即像这样的smth等效)

for (auto element: range(begin, end)) {
    if (predicate(element)) {
        do_smth();
    }
}

我的解决方案

我想到的近似实现是以下(伪代码):

struct Wrapper {
    op++() {
        do {
           ++value;
        while (!predicate(*value));
    }
    op*() {
        return *value;
    }
    op !=(Iterator other) {
        return value != other.value;
    }
    Iterator value;
}

返回对象的begin()类似

value = begin;
while (!predicate(*value)) ++value;
return Wrapper(value)

end()只是Wrapper(end)

注意事项

在此实施中我不喜欢什么:

  • 单纯:我只需要过滤,并且必须编写大量代码
  • 初始化有点难看 - 必须在那里增加
  • 如果我不会遍历所有对象(会破坏或只是不使用任何值),我会迭代额外的(到下一个未使用的元素)

我可以在每次取消引用之前进行迭代(以修复第2点和第3点),但它会使!= end检查更加困难(要么我需要提前减少结果,要么在检查中使用增量,这意味着将输入范围传递两次在周期中)

要求

我没有特定的语言版本要求,甚至对尚未批准的实施感兴趣。但是C ++ 11将是最伟大的

我没有支持迭代器类别的特定要求。我相信我会与ForwardIterators合作。

我对代码的可理解性及其效率感兴趣。

任何更接近银弹的解决方案? :)

1 个答案:

答案 0 :(得分:1)

您可以使用BOOST filter_iterator。以下是链接页面中的示例:

struct is_positive_number {                                                                         
  bool operator()(int x) { return 0 < x; }                                                          
  };                                                                                                

int main()                                                                                          
{                                                                                                   
  int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 };                                                      
    const int N = sizeof(numbers_)/sizeof(int);                                                     

  typedef int* base_iterator;                                                                       
    base_iterator numbers(numbers_);                                                                

  // Example using filter_iterator                                                                  
    typedef boost::filter_iterator<is_positive_number, base_iterator>                               
        FilterIter;                                                                                 

  is_positive_number predicate;                                                                     
    FilterIter filter_iter_first(predicate, numbers, numbers + N);                                  
      FilterIter filter_iter_last(predicate, numbers + N, numbers + N);                             

  std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " "));       
    std::cout << std::endl;                                                                         

  // Example using make_filter_iterator()                                                           
    std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),                
                boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),          
                        std::ostream_iterator<int>(std::cout, " "));                                
                          std::cout << std::endl;                                                   

  // Another example using make_filter_iterator()                                                   
    std::copy(                                                                                      
          boost::make_filter_iterator(                                                              
                std::bind2nd(std::greater<int>(), -2)                                               
                        , numbers, numbers + N)                                                     

    , boost::make_filter_iterator(                                                                  
              std::bind2nd(std::greater<int>(), -2)                                                 
                  , numbers + N, numbers + N)                                                       

    , std::ostream_iterator<int>(std::cout, " ")                                                    
      );                                                                                            

  std::cout << std::endl;                                                                           

  return boost::exit_success;                                                                       
}                                                                                                   
相关问题