我有以下代码,用于计算向量
中的唯一值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;
// testinput.txt中的内容在
之下5
2 4 4 2 4
1 4 1 6 4
输出显示如下
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
我的代码中有什么错误?
答案 0 :(得分:2)
根据documentation of std::unique
它
[e]限制除了连续等效元素组中的第一个元素之外的所有元素
(强调我的)。
因此,它不会删除所有重复的值,只删除相邻的值,例如[1 2 2 3 3 3 1 1 3 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] lements使用
operator==
进行比较。
另请注意,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循环:而不是
for(auto i = 0; i < myVec.size(); ++i) {
// Do something with myVec[i]
}
写
for(auto it = myVec.cbegin(); it != myVec.cend(); ++it) {
// Do something with *it
}
或者,迭代整个向量,
for(unsigned int val : myVec) {
// Do something with val
}
答案 1 :(得分:2)
来自the docs:
std::unique
从[first, last)
范围内的每个连续等效元素组中消除除第一个元素之外的所有元素,并为该范围的新逻辑结束返回一个过去的结束迭代器。
看到连续这个词,这意味着如果向量被排序,它只会删除重复项,并且重复是连续的顺序。
在调用std::unique
答案 2 :(得分:0)
正如其他答案所指出的,std::unique
删除了连续的重复项。这允许它是单程算法。
如果要在不更改剩余元素顺序的情况下删除非连续重复项,则必须编写不同的函数来执行此操作。这通常需要在输入范围内多次通过。
这是一个简单的实现,以匹配std::unique
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;
}
接受BinaryPredicate
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;
}