我想使用 set 删除重复元素并在插入时保持顺序
I want use set to remove duplicate element and keep the order when they insert
我想使用 set 来删除重复的元素并同时保持它们的顺序。所以我尝试更改比较参数,让它们按照插入的顺序排序。
#include <set>
#include <iostream>
using namespace std;
template <class T>
struct compare
{
bool operator() (T x, T y)
{
return true;
}
};
void main()
{
set<int,compare<int>> one;
one.insert(5);
one.insert(3);
one.insert(9);
one.insert(1);
one.insert(5);
one.insert(5);
}
来自 IDE 的表达式是 :invaild operator <
std::set
依靠比较器来保持严格的弱排序并确保每个值都是唯一的。您不能按插入顺序进行 std::set
排序。
一种可能的解决方案是使用两个容器,一个 std::set
用于包含唯一元素,一个 std::vector
索引用于保持它们插入的顺序。该向量可能包含集合中的迭代器。
用自己的迭代器将这两个容器封装在您自己的 class 中可能会很方便。这是一个简单的实现:
class MySetIterator {
std::vector<std::set<int>::iterator>::iterator pos;
public:
MySetIterator(std::vector<std::set<int>::iterator>::iterator pos) : pos(pos) {}
int operator*() { return **pos; }
MySetIterator& operator++() { ++pos; return *this; }
bool operator!=(const MySetIterator& rhs) { return pos != rhs.pos; }
};
class MySet {
std::set<int> vals;
std::vector<std::set<int>::iterator> order;
public:
void insert(int val) {
auto ret = vals.insert(val);
if (ret.second)
order.push_back(ret.first);
}
MySetIterator begin() { return {order.begin()}; }
MySetIterator end() { return {order.end()}; }
};
int main() {
MySet my_set;
my_set.insert(5);
my_set.insert(3);
my_set.insert(9);
my_set.insert(1);
my_set.insert(5);
my_set.insert(5);
for (int val : my_set)
std::cout << val << " ";
}
其他可能的解决方案是使用 boost::multi_index。
#include <iostream>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
namespace boost_mi = boost::multi_index;
typedef boost::multi_index_container<
int,
boost_mi::indexed_by<
boost_mi::random_access<>, // preserves insertion order
boost_mi::ordered_unique<boost_mi::identity<int> > // removes duplicates
>
> MySet;
int main()
{
MySet my_set;
my_set.push_back(5);
my_set.push_back(3);
my_set.push_back(9);
my_set.push_back(1);
my_set.push_back(5);
my_set.push_back(5);
for (auto val : my_set) {
std::cout << val << std::endl;
}
return 0;
}
我想使用 set 来删除重复的元素并同时保持它们的顺序。所以我尝试更改比较参数,让它们按照插入的顺序排序。
#include <set>
#include <iostream>
using namespace std;
template <class T>
struct compare
{
bool operator() (T x, T y)
{
return true;
}
};
void main()
{
set<int,compare<int>> one;
one.insert(5);
one.insert(3);
one.insert(9);
one.insert(1);
one.insert(5);
one.insert(5);
}
来自 IDE 的表达式是 :invaild operator <
std::set
依靠比较器来保持严格的弱排序并确保每个值都是唯一的。您不能按插入顺序进行 std::set
排序。
一种可能的解决方案是使用两个容器,一个 std::set
用于包含唯一元素,一个 std::vector
索引用于保持它们插入的顺序。该向量可能包含集合中的迭代器。
用自己的迭代器将这两个容器封装在您自己的 class 中可能会很方便。这是一个简单的实现:
class MySetIterator {
std::vector<std::set<int>::iterator>::iterator pos;
public:
MySetIterator(std::vector<std::set<int>::iterator>::iterator pos) : pos(pos) {}
int operator*() { return **pos; }
MySetIterator& operator++() { ++pos; return *this; }
bool operator!=(const MySetIterator& rhs) { return pos != rhs.pos; }
};
class MySet {
std::set<int> vals;
std::vector<std::set<int>::iterator> order;
public:
void insert(int val) {
auto ret = vals.insert(val);
if (ret.second)
order.push_back(ret.first);
}
MySetIterator begin() { return {order.begin()}; }
MySetIterator end() { return {order.end()}; }
};
int main() {
MySet my_set;
my_set.insert(5);
my_set.insert(3);
my_set.insert(9);
my_set.insert(1);
my_set.insert(5);
my_set.insert(5);
for (int val : my_set)
std::cout << val << " ";
}
其他可能的解决方案是使用 boost::multi_index。
#include <iostream>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
namespace boost_mi = boost::multi_index;
typedef boost::multi_index_container<
int,
boost_mi::indexed_by<
boost_mi::random_access<>, // preserves insertion order
boost_mi::ordered_unique<boost_mi::identity<int> > // removes duplicates
>
> MySet;
int main()
{
MySet my_set;
my_set.push_back(5);
my_set.push_back(3);
my_set.push_back(9);
my_set.push_back(1);
my_set.push_back(5);
my_set.push_back(5);
for (auto val : my_set) {
std::cout << val << std::endl;
}
return 0;
}