看到這篇 有感而發,現實中常見的問題之一,為了方便說明,把原先的問題簡化,求鄰近元素後者比前面大的數對
最初的方法 原先我只會用這種方法
1 2 3 4 5 6 7 int calc (const std ::vector <int > &v) { int count = 0 ; for (size_t i = 0 ; i < v.size() - 1 ; i++) if (v[i + 1 ] > v[i]) count++; return count; }
利用vector來作,實在不高明
Better Solution 參考上面blog的作法
1 2 3 4 5 6 7 8 9 template <typename T>int calc (const T& v) { int count = 0 ; for (auto it1 = v.cbegin(), it2 = v.cend(); it1 != v.cend(); it2 = it1, ++it1) if (it2 != v.end()) if (*it1 > *it2) count++; return count; }
好一點了,不限定要是vector,不過還是要思考一下it1和it2的關聯性
Range-V3 Solution 可能成為下一代STL的Range-v3,其作法就類似FP中的pipeline的方式處理,隱藏了iterator的存在
1 2 3 4 5 6 7 template <typename T>int calc (const T& v) { using namespace ranges; auto larger = [](auto front, auto back) { return front > back; }; return distance(v | view::adjacent_remove_if(larger)) - 1 ; }
Range-V3 Solution Ver 2, Sliding Window Range-v3最近加入了Sliding Window的觀念,比起上面的方式更加通用,不過還是不知道怎麼把他轉成Ranges轉成Tuple,只好寫成這樣
1 2 3 4 5 6 7 8 9 10 11 template <typename T>int calc (const T& v) { using namespace ranges; return count_if(v | view::sliding(2 ), [](const auto &v) { auto begin = ranges::begin(v); auto front = *begin++; auto back = *begin++; return front < back; }); }
Conclusion 抽象的程度越高,Debug的難度也自然越高,看著gcc或是clang吐出來的compilation error真是一個頭兩個大,尤其是跟Range-v3扯上關係
Reference — range-v3 — Super expressive code by Raising Levels of Abstraction — Ranges: the STL to the Next Level