擦除重复元素保持秩序
erase duplicate elements keeping order
我想从矢量中删除重复元素,同时保持矢量的当前顺序。
下面我有一个建议的实现。首先,这样安全吗?
其次,是否有更好的方法来做到这一点,从“使用 C++ 算法而不是重新发明轮子”的角度来看,效率更高或更好。
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
int main()
{
using namespace std;
std::vector<int> v= {1, 7, 2, 3, 8, 4, 5, 3, 2, 3, 2, 6, 2, 3, 2, 9, 10, 1, 2, 2, 1};
std::vector<int>::iterator finalEnd = v.end();
for (auto vIter = v.begin(); vIter != v.end(); ++vIter) {
for (auto nextvIter = vIter + 1; nextvIter != v.end(); ++nextProjIter) {
if (*vIter == *nextvIter)
finalEnd = std::remove(vIter, finalEnd, *nextvIter);
}
}
v.erase(finalEnd, v.end());
for(auto p : v)
cout << p << " ";
//Should return: 1 7 2 3 8 4 5 6 9 10
return EXIT_SUCCESS;
}
通过构造一个新的vector,你可以将这个vector初始化为不重复的。您可以为此使用查找功能。我建议你搜索 std :: find
std::vector<int> v= {1, 7, 2, 3, 8, 4, 5, 3, 2, 3, 2, 6, 2, 3, 2, 9, 10, 1, 2, 2, 1};
std::vector<int> nonDuplicateVect;
for (int element : v)
if(std::find(nonDuplicateVect.begin(), nonDuplicateVect.end(), element) == nonDuplicateVect.end())
nonDuplicateVect.push_back(element);
for (int element : nonDuplicateVect)
std::cout << element << " ";
std::cout << "\n";
实现此目的的方法之一是使用 std::unordered_set to keep track of duplicates and std::stable_partition 将重复项与单独的值分开,同时保留项目的顺序:
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_set>
int main()
{
std::unordered_set<int> numSet;
std::vector<int> v= {1, 7, 2, 3, 8, 4, 5, 3, 2, 3, 2, 6, 2, 3, 2, 9, 10, 1, 2, 2, 1};
auto iter = std::stable_partition(v.begin(), v.end(), [&](int n)
{ bool ret = !numSet.count(n); numSet.insert(n); return ret; }); // returns true if the item has not been "seen"
v.erase(iter, v.end());
for(auto p : v)
std::cout << p << " ";
}
输出:
1 7 2 3 8 4 5 6 9 10
std::stable_partition
将 return true
如果该项目还没有看到,因此将其放在分区点的左侧。完成后,指向分区点的迭代器被 returned,我们使用此迭代器从该点到向量末尾进行一次擦除。请注意,lambda 函数会为处理的每个项目更新 unordered_set
。
之所以使用std::stable_partition
而不是std::remove_if
是因为std::remove_if
不能保证按顺序处理项目。例如,实现可以先处理该数据中的第二个 1
,而不是第一个 1
。所以为了保险起见stable_partition
不会擦除元素,只是把元素放在正确的位置,为最后的擦除做准备。
我想从矢量中删除重复元素,同时保持矢量的当前顺序。
下面我有一个建议的实现。首先,这样安全吗?
其次,是否有更好的方法来做到这一点,从“使用 C++ 算法而不是重新发明轮子”的角度来看,效率更高或更好。
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
int main()
{
using namespace std;
std::vector<int> v= {1, 7, 2, 3, 8, 4, 5, 3, 2, 3, 2, 6, 2, 3, 2, 9, 10, 1, 2, 2, 1};
std::vector<int>::iterator finalEnd = v.end();
for (auto vIter = v.begin(); vIter != v.end(); ++vIter) {
for (auto nextvIter = vIter + 1; nextvIter != v.end(); ++nextProjIter) {
if (*vIter == *nextvIter)
finalEnd = std::remove(vIter, finalEnd, *nextvIter);
}
}
v.erase(finalEnd, v.end());
for(auto p : v)
cout << p << " ";
//Should return: 1 7 2 3 8 4 5 6 9 10
return EXIT_SUCCESS;
}
通过构造一个新的vector,你可以将这个vector初始化为不重复的。您可以为此使用查找功能。我建议你搜索 std :: find
std::vector<int> v= {1, 7, 2, 3, 8, 4, 5, 3, 2, 3, 2, 6, 2, 3, 2, 9, 10, 1, 2, 2, 1};
std::vector<int> nonDuplicateVect;
for (int element : v)
if(std::find(nonDuplicateVect.begin(), nonDuplicateVect.end(), element) == nonDuplicateVect.end())
nonDuplicateVect.push_back(element);
for (int element : nonDuplicateVect)
std::cout << element << " ";
std::cout << "\n";
实现此目的的方法之一是使用 std::unordered_set to keep track of duplicates and std::stable_partition 将重复项与单独的值分开,同时保留项目的顺序:
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_set>
int main()
{
std::unordered_set<int> numSet;
std::vector<int> v= {1, 7, 2, 3, 8, 4, 5, 3, 2, 3, 2, 6, 2, 3, 2, 9, 10, 1, 2, 2, 1};
auto iter = std::stable_partition(v.begin(), v.end(), [&](int n)
{ bool ret = !numSet.count(n); numSet.insert(n); return ret; }); // returns true if the item has not been "seen"
v.erase(iter, v.end());
for(auto p : v)
std::cout << p << " ";
}
输出:
1 7 2 3 8 4 5 6 9 10
std::stable_partition
将 return true
如果该项目还没有看到,因此将其放在分区点的左侧。完成后,指向分区点的迭代器被 returned,我们使用此迭代器从该点到向量末尾进行一次擦除。请注意,lambda 函数会为处理的每个项目更新 unordered_set
。
之所以使用std::stable_partition
而不是std::remove_if
是因为std::remove_if
不能保证按顺序处理项目。例如,实现可以先处理该数据中的第二个 1
,而不是第一个 1
。所以为了保险起见stable_partition
不会擦除元素,只是把元素放在正确的位置,为最后的擦除做准备。