今天就跟大家聊聊有关使用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++怎么移除序列中连续重复的特定值有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。