溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

使用C++怎么移除序列中連續重復的特定值

發布時間:2021-04-14 18:01:11 來源:億速云 閱讀:250 作者:Leah 欄目:編程語言

今天就跟大家聊聊有關使用C++怎么移除序列中連續重復的特定值,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

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;
}

看完上述內容,你們對使用C++怎么移除序列中連續重復的特定值有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女