我发现list::unique()
只删除列表中的连续元素。我想知道该方法的功能是这样的原因。
Remove duplicates from a list解释了如何从列表中删除重复元素,但它没有解释为什么只删除连续元素。
以下是我的测试代码:
#include <algorithm>
#include <iostream>
#include <list>
#include <string>
#include <utility>
using namespace std;
void print_message( const pair<int,string>& message )
{
cout << message.first << " - " << message.second << endl;
}
int main( )
{
list< pair< int, string > > message;
list< pair< int, string > >::iterator ip;
message.push_back( make_pair( 1, string("Test Foo One")) );
message.push_back( make_pair( 1, string("Test Foo Two")) );
message.push_back( make_pair( 1, string("Test Foo Two")) );
message.push_back( make_pair( 1, string("Test Foo Three" )) );
message.push_back( make_pair( 1, string("Test Foo Two" )));
message.push_back( make_pair( 1, string("Test Foo Two")) );
cout << "ORIGINAL MESSAGES" << endl;
ip = message.begin();
while(ip!=message.end()) {
print_message(*ip);
ip++;
}
message.unique();
cout << "\nSEQUENTIAL DUPLICATES REMOVED" << endl;
ip = message.begin();
while(ip!=message.end()) {
print_message(*ip);
ip++;
}
}
为什么此方法list::unique()
仅用于删除列表中的连续重复元素?
答案 0 :(得分:5)
标准库的设计遵循为用户提供一套全面的基本,相对简约的算法&#34;构建块&#34;的方法,如果需要,可以手动组合成更复杂的算法。删除连续的等效元素发生在这种简约算法上。去除非有序序列中的非连续等效元素绝对不是简约算法。对于非有序序列,它不是自然算法。
通常,为了在非有序容器中实现后者,用户必须执行sort
然后执行unique
。由于该库已经提供sort
和unique
作为基本&#34;构建块&#34;,因此无需提供可用的unique
算法的单独版本与非相邻元素。从这个意义上来说,sort
和unique
形成一个惯用的对,就像众所周知的erase–remove idiom中的remove_if
和erase
一样。
另外,实现非相邻unique
的问题在于&#34;清洁&#34;这种功能的实现将要求非重新排序操作,即应该删除重复元素,但其余元素的相对顺序应保持不变。不可能实现简约&#34;构建块&#34;等功能。而且我说它并不需要它,因为在大多数实际情况下,用户会对sort
- 然后 - unique
组合感到满意,或者使用不同的容器完全打字。
答案 1 :(得分:2)
我同意你的前提,即unique
这个词的用法并不理想,相对于较长的名字,可能是consecutive_unique
。 “(操作越奇怪,名称应该越长)”我不会 - 我自己 - 认为仅仅unique
这个名字很好,使用更长的名字然后为你想要的东西保存短名称。
所以......为什么呢?我想起了hypothetical interview with Richard Feynman关于“为什么井盖为圆形”的问题。我会引用这一点:
采访者:您认为存在安全问题吗?我的意思是,不能将方形盖子掉进洞里并伤害某人吗?
费曼:不太可能。方形盖有时用于预制拱顶,其中进入通道也是方形的。盖子比通道大,并且位于沿整个周边支撑它的壁架上。盖子通常由坚固的金属制成并且非常重。假设一个2英尺见方的开口和1-1 / 2英寸的壁架宽度。为了让它落入,你必须抬起盖子的一侧,然后将其旋转30度,使盖子清除壁架,然后在重心前将盖子从水平方向倾斜近45度会转移到足以让它落入。是的,这是可能的,但非常不可能。有权打开井盖的人员可以很容易地接受安全培训。
在这种情况下,原因将归结为:“授权打开井盖的人员可以很容易地接受安全培训。”
即使C ++函数具有“直观”名称,也不能保护其行为。您必须认识到使用库类或函数的许多细节。在某种程度上,训练你想象每个方法或函数被称为X是一件好事......所以你要看看X实际承诺的合同。