我有一系列名字,但我只需要唯一的名字。我使用std::set
以便清除重复内容。然而,我需要名称以与输入相同的顺序显示 。这意味着如果我的输入是:
Mary
Mary
John
John
John
Apple
Apple
Apple
[编辑]:在检查评论/答案后,我想强调每个名字都出现在组中,并且稍后不会在输入中显示。参考示例,Mary
出现两次,即。它稍后不再出现。[/ Edit]
我希望我的输出为:
Mary
John
Apple
使用std::set
,我得到了排序的一个:
Apple
John
Mary
我发现有unordered_set
(来自{cplusplus.com})。这个再次不保持输入顺序。
问题:
std::set
排序?std::set
}。现在,如果我无法阻止set
排序,那么编写我自己的排序方法怎么样,但总是将输入的第一个元素作为最小元素返回? (如果我能了解如何做到这一点......)std
中还有其他东西可以将一组字符串减少为一个唯一的集合,但是不对它进行排序吗?谢谢!
答案 0 :(得分:6)
最简单的方法是保留2个集合,vector
和set
(或unordered_set
)。这将消耗更多内存,但会使用set
检查重复项(O(log N)
时间内)和vector
以维持顺序。
set
也可以包含项目向量中的位置,并具有谓词{{1}}。稍微复杂,因为您需要在特殊谓词中存储向量/指针。但是它可以完成并且将使用可能更少的内存,因为您只有一个字符串集合而另一个是int。此外,它还充当索引,能够快速找到特定项目的位置。
答案 1 :(得分:1)
您正在尝试更改基本设计实施。相反,你应该重新思考自己的设计,而不是试图违背标准库的内容。
我的解决方案是使用std::vector<std::string>
并根据您的计划目标:
或
这些实现中的任何一个都将保留插入顺序,并且您可以按照自己的条件处理重复项。
这是第二个版本:
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string> collection;
std::vector<std::string> getUniques(std::vector<std::string> collection)
{
std::vector<std::string> uniques;
for (std::string name : collection)
{
if (std::find(uniques.begin(), uniques.end(), name) == uniques.end())
uniques.push_back(name);
}
return uniques;
}
int main()
{
collection.push_back("John");
collection.push_back("John");
collection.push_back("Sally");
collection.push_back("Kent");
collection.push_back("Jim");
collection.push_back("Sally");
std::vector<std::string> uniques = getUniques(collection);
for (std::string name : uniques)
std::cout << name << std::endl;
}
收率:
John
Sally
Kent
Jim
答案 2 :(得分:0)
第一个问题:没有。根据cplusplus.com:
集合是按特定订单存储唯一元素的容器。
第二个问题:你需要有2点数据才能做到这一点。第一个是你的实际字符串,第二个是'插入索引',所以你可以存储插入顺序。
所以基本上,如果你把std :: pair放在你的std :: set中并且基本上增加你放在std :: pair中的数字,你就可以这样做。但是,一旦你这样做,就意味着每个std :: pair都是唯一的,这意味着'std :: set'的使用已经消失了。
上面已经听起来太复杂了,为什么不选择更合适的容器呢? 例如,您可以使用std :: vector并在插入时删除双精度数。
如果这太慢(O(N)插入),你可以有一个std :: vector用于有序存储,并在它旁边保留一个std :: set,以便能够快速检查唯一性。
答案 3 :(得分:0)
从你的例子来看,似乎相等的价值观相互依存。
如果是这种情况,则不需要复杂性:您可以开始填充新数组并逐个复制元素,除非它们与前一个相同。这是一个简单的O(N)过程。
答案 4 :(得分:0)
而不是std :: set使用std :: unique
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
bool myfunction (char *i,char *j)
{
int x=strcmp(i,j);
if(!x)
return 1;
else
return 0;
}
int main ()
{
char mywords[][10] = {"Mary","Mary","John","John","John","Apple","Apple","Apple"};
vector<char*> myvector (mywords,mywords+8);
vector<char*>::iterator it;
it = unique (myvector.begin(), myvector.end(), myfunction);
myvector.resize(distance(myvector.begin(),it));
cout << "Output:";
for (it=myvector.begin(); it!=myvector.end(); ++it)
cout << ' ' << *it;
cout << endl;
return 0;
}
答案 5 :(得分:0)
在阅读完所有评论和答案后,我认为回答自己问题的最直接方法是使用std::vector
和std::unique
。
要注意的是:
Mary
出现2次,则列表的其余部分将不再显示。所以这是我的编码:
#include <vector>
int main()
{
std::vector<std::string> names;
std::vector<std::string>::iterator last;
std::vector<std::string>::iterator it;
names.push_back("Mary");
names.push_back("Mary");
names.push_back("John");
names.push_back("John");
names.push_back("John");
names.push_back("Apple");
names.push_back("Apple");
names.push_back("Apple");
last = std::unique(names.begin(), names.end());
for (it = names.begin(); it != last; ++it)
std::cout << *it << endl;
}
所以输出将是(我想要的):
Mary
John
Apple
就是这样。感谢那些贡献者。随意评论,尤其是关于效率的评论。