国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

C++移除序列中連續重復的特定值示例代碼

2020-01-26 13:33:11
字體:
來源:轉載
供稿:網友

前言

最近在寫 YTL 中的字符串相關輔助函數。實現到 split 函數時,希望能夠實現類似 Python 當中的 str.split 方法的功能。

If sep is not specified or is None , a different splitting algorithm is applied: runs of consecutive whitespace are regarded as a single separator, and the result will contain no empty strings at the start or end if the string has leading or trailing whitespace.

―― https://docs.python.org/3/library/stdtypes.html#str.split

也就是說,在最基本的 split 的基礎上,要添加兩個功能:

•刪除輸入字符串首尾的空白;

•將字符串中的連續分隔符當成一個分隔符看待。

前一個功能很好實現。將空白符保存在 const char* trim_chars = " /t/n/r/v/f" 當中,然后使用 std::string::find_first_not_of 以及 std::string::find_last_not_of 即可找到有效內容的起止位置,最后再 std::string::erase 一下就好了。

后一個功能也不復雜。但要寫得優雅――最好是能利用上標準庫的設施――就不那么容易了。

std::unique 的基本用法

std::unique 是定義在 algorithm 頭文件內的容器算法。它有兩種基本形式:

template< class ForwardIt >ForwardIt unique( ForwardIt first, ForwardIt last );template< class ForwardIt, class BinaryPredicate >ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPredicate p );

其中,第一種形式是第二種形式的特例,它等價于 BinaryPredicate p 為連續兩元素相等性判斷時的第二種形式:

template< class ForwardIt,   class BinaryPredicate =   std::function<bool(const typename std::iterator_traits<ForwardIt>::value_type&,    const typename std::iterator_traits<ForwardIt>::value_type&)>ForwardIt unique( ForwardIt first, ForwardIt last,   BinaryPredicate p = [](const typename std::iterator_traits<ForwardIt>::value_type& lhs,         const typename std::iterator_traits<ForwardIt>::value_type& rhs) {          return lhs == rhs; });

這也就是說,第一種形式的 std::unique 會找到每個連續重復的區間,而后保留這些區間的首個元素,最后返回新序列邏輯上的尾后迭代器。例如, aabbccaa 經過 std::unique 處理之后得到:

abca????

這里用箭頭標出的位置,即是 std::unique 的返回值所指向的位置。需要注意的是,經過 std::unique 處理之后,容器的實際大小沒有發生改變,甚至邏輯尾后迭代器到容器實際尾后迭代器之間的左閉右開區間內的迭代器仍然是可解引用的(dereferenceable)。但這部分區間內的元素的值是不確定的。因此,在使用 std::unqiue 之后,往往會調用容器的 erase 函數成員,刪除邏輯尾后迭代器開始的所有元素。例如:

// #include <string>// #include <algorithm>std::string source("aabbccaa");source.erase(std::unique(source.begin(), source.end()), source.end());std::cout << source << std::endl; // expect result: abca

只對特定內容進行 std::unique 操作

回到最開始的問題。我們需要的功能,是針對分隔符 sep 進行操作,將連續出現的 sep 壓縮成一個。 std::unique 的默認行為則不然,它會將所有連續出現的元素都壓縮成一個――不光是 sep 。為此,我們需要實現自己的 BinaryPredicate 。首先,由于我們要指定具體需要被 std::unique 壓縮的元素,我們必然要將其作為函數參數傳入函數。于是我們有以下實現:

// #include <functional>template <typename T>bool AreConsecutiveElements(const T& target, const T& lhs, const T& rhs) { return (lhs == rhs) and (lhs == target);}

std::unique 要求一個二元謂詞( BinaryPredicate ),但此處我們實現的是三元謂詞。于是,好在 target 總是應當預先給出的,所以我們可以利用 std::bind 將 target 綁定在 AreConsecutiveElements 的第一個參數上,產生一個二元謂詞。

// #include <functional>// using namespace std::placeholders;// #include <string>// #include <algorithm>const char target = 'b'auto binp = std::bind(AreConsecutiveElements, target, _1, _2);std::string source("aabbccaa");source.erase(std::unique(source.begin(), source.end(), binp), source.end());std::cout << source << std::endl; // expect result: aabccaa

這里,我們將 'b' 作為壓縮目標,并將其與 AreConsecutiveElements 綁定在一起,產生一個新的二元謂詞。最終輸出期待的結果。

附: std::unique 的一個可能實現

template<class ForwardIt, class BinaryPredicate>ForwardIt unique(ForwardIt first, ForwardIt last, BinaryPredicate p) { if (first == last) { return last; } ForwardIt result = first; while (++first != last) { if (!p(*result, *first) && ++result != first) {  *result = std::move(*first); } } return ++result;}

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 鹤峰县| 洪雅县| 湖口县| 抚州市| 壤塘县| 潞城市| 克拉玛依市| 汤阴县| 漠河县| 赤水市| 东方市| 习水县| 博爱县| 平度市| 余姚市| 嘉义县| 嘉义市| 贞丰县| 台前县| 澄迈县| 叶城县| 昌邑市| 都江堰市| 清水河县| 鹤峰县| 大余县| 永平县| 莎车县| 金川县| 利川市| 临城县| 安顺市| 朝阳市| 房产| 吐鲁番市| 汶川县| 石屏县| 额济纳旗| 安丘市| 鹰潭市| 文化|