C++ stl向量中的唯一值
我有下面的代码来计算向量中的唯一值C++ stl向量中的唯一值,c++,vector,C++,Vector,我有下面的代码来计算向量中的唯一值 bool uniqueCompressVectorCompareFunction (unsigned int num1, unsigned int num2) { return (num1 == num2); } // redirect input from stream to file. std::ifstream inputFile("testinput.txt"); std::streambuf* pcurrRdBuf = std::cin.rd
bool uniqueCompressVectorCompareFunction (unsigned int num1, unsigned int num2) {
return (num1 == num2);
}
// redirect input from stream to file.
std::ifstream inputFile("testinput.txt");
std::streambuf* pcurrRdBuf = std::cin.rdbuf();
std::cin.set_rdbuf(inputFile.rdbuf());
unsigned int uiNoOfFishes = 0;
std::cin >> uiNoOfFishes;
std::vector<unsigned int> vecOfLenOfFishes(uiNoOfFishes);
std::vector<unsigned int> vecOfTimeHeadOfFishes(uiNoOfFishes);
// get length of fishes
for(unsigned int uiIdx = 0; uiIdx < uiNoOfFishes; uiIdx++) {
std::cin >> vecOfLenOfFishes[uiIdx];
}
// get time head of fishes
for(unsigned int uiIdx = 0; uiIdx < uiNoOfFishes; uiIdx++) {
std::cin >> vecOfTimeHeadOfFishes[uiIdx];
}
std::cout << "Actual input length of fishes: " << std::endl;
for(unsigned int uiIdx = 0; uiIdx <vecOfLenOfFishes.size(); uiIdx++) {
std::cout << vecOfLenOfFishes[uiIdx] << " ";
}
std::cout << std::endl;
std::cout << "Actual input time head of fishes: " << std::endl;
for(unsigned int uiIdx = 0; uiIdx <vecOfTimeHeadOfFishes.size(); uiIdx++) {
std::cout << vecOfTimeHeadOfFishes[uiIdx] << " ";
}
std::cout << std::endl;
std::vector<unsigned int> vecUniqueInputValues;
// copy length of fishes.
unsigned int uiUniqueVecIdx = 0;
for(; uiUniqueVecIdx < uiNoOfFishes; uiUniqueVecIdx++) {
vecUniqueInputValues.push_back(vecOfLenOfFishes[uiUniqueVecIdx]);
}
// copy time head of fishes.
for(unsigned int uiIdx = 0; uiIdx < uiNoOfFishes; uiIdx++, uiUniqueVecIdx++) {
vecUniqueInputValues.push_back( vecOfTimeHeadOfFishes[uiIdx]);
}
// using predicate comparison:
std::unique (vecUniqueInputValues.begin(), vecUniqueInputValues.end(), uniqueCompressVectorCompareFunction);
std::cout << "compressInputData unique values sorted: " << std::endl;
for(unsigned int uiIdx = 0; uiIdx <vecUniqueInputValues.size(); uiIdx++) {
std::cout << vecUniqueInputValues[uiIdx] << " ";
}
std::cout << std::endl;
输出如下所示
Actual input length of fishes:
2 4 4 2 4
Actual input time head of fishes:
1 4 1 6 4
compressInputData total values:
2 4 4 2 4 1 4 1 6 4
compressInputData unique values sorted:
2 4 2 4 1 4 1 6 4 4
我希望压缩输入的唯一值应该是
1 2 4 6
我的代码中有什么bug?根据it
[e] 从每个连续的等效元素组中删除除第一个元素以外的所有元素
我的
因此,它不会删除所有重复出现的值,只删除相邻的值,例如将[1 2 3 3 3 1 3 2 2]减少到[1 2 3 1 3 2]
如果只希望保持整体唯一元素,则应首先对向量进行排序:
std::sort(vecUniqueInputValues.begin(), vecUniqueInputValues.end());
// Vector is now [1, 1, 2, 2, .., 2, 4, .., 4, 5, ... ]
std::unique (vecUniqueInputValues.begin(), vecUniqueInputValues.end(),
uniqueCompressVectorCompareFunction);
一些小问题
比较函数似乎有点多余——如果您不指定它的话
[e] 使用运算符==比较元素
还请注意,std::unique实际上只对元素进行洗牌,以便所有唯一的连续元素都位于向量的开头-您仍然可以在输出的末尾两次看到值4。您应该获取std::unique的结果-它是一个迭代器,指向唯一范围的末尾:
auto endOfUniqueRange = std::unique(...);
std::cout << "compressInputData unique values sorted: " << std::endl;
for(auto& uiIt = vecUniqueInputValues.cbegin(); uiIt != endOfUniqueRange ; ++uiIt) {
std::cout << *uiIt << " ";
}
std::cout << std::endl;
或者,迭代整个向量
for(unsigned int val : myVec) {
// Do something with val
}
据it部门称
[e] 从每个连续的等效元素组中删除除第一个元素以外的所有元素
我的
因此,它不会删除所有重复出现的值,只删除相邻的值,例如将[1 2 3 3 3 1 3 2 2]减少到[1 2 3 1 3 2]
如果只希望保持整体唯一元素,则应首先对向量进行排序:
std::sort(vecUniqueInputValues.begin(), vecUniqueInputValues.end());
// Vector is now [1, 1, 2, 2, .., 2, 4, .., 4, 5, ... ]
std::unique (vecUniqueInputValues.begin(), vecUniqueInputValues.end(),
uniqueCompressVectorCompareFunction);
一些小问题
比较函数似乎有点多余——如果您不指定它的话
[e] 使用运算符==比较元素
还请注意,std::unique实际上只对元素进行洗牌,以便所有唯一的连续元素都位于向量的开头-您仍然可以在输出的末尾两次看到值4。您应该获取std::unique的结果-它是一个迭代器,指向唯一范围的末尾:
auto endOfUniqueRange = std::unique(...);
std::cout << "compressInputData unique values sorted: " << std::endl;
for(auto& uiIt = vecUniqueInputValues.cbegin(); uiIt != endOfUniqueRange ; ++uiIt) {
std::cout << *uiIt << " ";
}
std::cout << std::endl;
或者,迭代整个向量
for(unsigned int val : myVec) {
// Do something with val
}
发件人:
unique从范围[first,last]中的每个连续的等效元素组中消除除第一个元素以外的所有元素,并为范围的新逻辑端返回一个结束迭代器
请参见单词Continuous,这意味着仅当向量已排序且重复顺序为连续时,才会删除重复项
在从以下位置调用std::unique之前对向量进行排序:
unique从范围[first,last]中的每个连续的等效元素组中消除除第一个元素以外的所有元素,并为范围的新逻辑端返回一个结束迭代器
请参见单词Continuous,这意味着仅当向量已排序且重复顺序为连续时,才会删除重复项
在调用std::unique之前对向量进行排序,正如其他答案所指出的,std::unique会删除连续的重复项。这允许它成为单次传递算法 如果要在不更改其余元素顺序的情况下删除非连续的重复项,则必须编写不同的函数来执行此操作。这通常需要在输入范围内进行多次传递 下面是一个简单的实现,用于匹配std::unique的签名
正如其他答案所指出的,std::unique删除了连续的重复项,这使得它成为一个单遍算法 如果要在不更改其余元素顺序的情况下删除非连续的重复项,则必须编写不同的函数来执行此操作。这通常需要在输入范围内进行多次传递 下面是一个简单的实现,用于匹配std::unique的签名
您必须在std::unique之前对向量进行排序:请参见示例:否则,您可以使用std::unordered_集来保持唯一值这可能是因为您减少了实际代码,但是函数uniquecompressvectorcomarefunction永远不应该存在。相反,如果您实际上只执行了一个等式,请省略functor参数mparison。这里回答了一个类似的问题:你必须在std::unique之前对向量进行排序:参见示例:否则,你可以使用std::unordered_集来保持唯一值。这可能是因为你减少了实际代码,但函数uniquecompressvectorcomarefunction永远不应该存在。相反,只需省略该函数即可参数,如果您实际上只是执行相等比较。这里回答了一个类似的问题:您仍然可以在一次传递中执行此操作。例如,您可以将看到的所有元素添加到哈希集中。在扫描向量时,您可能会遇到集合中已存在的元素并将其删除,或者遇到尚未看到的元素:保留它并将其添加到集合中。不是O1,而是单次传递。@需要可复制值和额外分配的CompuChip您仍然可以在单次传递中完成。例如,您可以添加所有t
他将您看到的元素转换为散列集。扫描向量时,您可能会遇到集合中已存在的元素并将其删除,或者遇到尚未看到的元素:将其保留并添加到集合中。不是O1,而是需要可复制值和额外分配的单通芯片
template <typename ForwardIterator>
ForwardIterator multipass_unique(ForwardIterator first, ForwardIterator last)
{
for (; first != last; ++first)
{
// Search the whole range for values that are equal to the current
// Any values removed shorten the range to search
last = std::remove(std::next(first), last, *first);
}
return last;
}
template <typename ForwardIterator, typename BinaryPredicate>
ForwardIterator multipass_unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred)
{
for (; first != last; ++first)
{
// Search the whole range for values that satisfy the predicate
// Any values removed shorten the range to search
last = std::remove_if(std::next(first), last, [=](auto val){ return pred(*first, val); });
}
return last;
}