2017-03-01 28 views
6

範囲の範囲を範囲の範囲にスライスして、隣接する範囲が境界要素を共有するように範囲-V3ライブラリを使用しようとしました。範囲を重複範囲の範囲に分割

以下を考慮してください

using namespace ranges; 

std::vector<int> v = { 1, 2, 3, 0, 4, 0, 5, 0, 6, 7, 8, 0, 0, 9 }; 
auto myRanges = v | /* something like adjacent split */ 
for_each(myRanges, [](auto&& range){ std::cout << range << std::endl;}); 

I領域は、2つの基準をfullfillsかどう基づく重複部分範囲に範囲を分割したい:

  1. 要素がゼロ
  2. の値を有するかどうかをまたは0の値を有する1つまたは複数の要素に隣接しています。

所望の出力:

[1,2,3] 
[3,0,4,0,5,0,6] 
[6,7,8] 
[8,0,0,9] 

私の試み:

auto degenerate = 
    [](auto&& arg){ 
    return distance(arg) < 2; 
    }; 

auto myRanges = v | view::split(0) | view::remove_if(degenerate); 
for_each(myRanges, [](auto&& range){ std::cout << range << std::endl;}); 

出力:

[1,2,3] 
[6,7,8] 

私は

  1. "挿入" かもしれない方法で途方に暮れてよ3〜6の範囲。
  2. 私が正しくあなたの要件を理解していれば、あなたはadjacent_findの面で発電機を実装することができ、8〜9
+0

なぜ移動参照を渡していますか?それはあなたのデータを壊すでしょう – Sugar

+3

@Sugar私は 'auto &&'の使用と、 '&&'がrvalue参照を暗示しているという印象を想定しています。この場合、そのsigilはrvalue参照を意味するのではなく、Scott Meyerのものが普遍的に参照するものを意味します。もっと見る(こちら)[https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers] – apmccartney

+1

[ここ](https://isocpp.org/blog/2012/11)/universal-references-in-c11-scott-meyers)は、apmccartneyのリンクの作業バージョンです。 –

答えて

2

の範囲を "追加":

template<typename IterT> 
struct seg_generator_ { 
    IterT it_, end_; 
    bool fz_ = true; 

    ranges::iterator_range<IterT> operator()() { 
     if (it_ == end_) { 
      return {it_, end_}; 
     } 

     auto n = ranges::adjacent_find(
      it_, end_, 
      [fz = std::exchange(fz_, !fz_)](auto const a, auto const b) { 
       return a && !b == fz; 
      } 
     ); 
     return { 
      std::exchange(it_, n), 
      n != end_ ? ranges::next(std::move(n)) : std::move(n) 
     }; 
    } 
}; 

template<typename RngT> 
auto seg_generator(RngT&& rng) -> seg_generator_<decltype(ranges::begin(rng))> { 
    return {ranges::begin(rng), ranges::end(rng)}; 
} 

int main() { 
    std::vector<int> const v{1, 2, 3, 0, 4, 0, 5, 0, 6, 7, 8, 0, 0, 9}; 
    auto myRanges = 
     ranges::view::generate(seg_generator(v)) 
     | ranges::view::take_while([](auto const& r) { return !r.empty(); }); 
    ranges::copy(myRanges, ranges::ostream_iterator<>{std::cout, "\n"}); 
} 

Online Demo

希望と同じくらい正確ではない... - [