设置存储混乱
Set storage confusion
我已经声明了这样的结构:
struct data{
vector<string> att;
string ds;
};
现在一个集合来存储来自多个数据元素的唯一数据
set<data> s;
基于不同的vector<string> att
和string ds
如何操作?
在不知道您希望如何比较您的结构的情况下,您可以尝试以下操作:
struct data
{
vector<string> att;
string ds;
friend bool operator < (const data& lhs, const data& rhs)
{
if (std::lexicographical_compare(lhs.att.begin(), lhs.att.end(), rhs.att.begin(), rhs.att.end()))
{
return true;
}
else if (std::lexicographical_compare(rhs.att.begin(), rhs.att.end(), lhs.att.begin(), lhs.att.end()))
{
return false;
}
else
{
return lhs.ds < rhs.ds;
}
}
};
我对这个解决方案不满意,因为它执行了两次字典顺序比较,效率很低。希望有人能提出更好的解决方案。
基本思路是,对于每个成员,比较左 < 右。如果为真,则 return 为真,否则比较右 < 左。如果为真,return 为假。否则,继续下一个成员。
注意:您可以阅读更多关于我用来比较事物的技巧 (std::tie
) in Implementing comparison operators via 'tuple' and 'tie', a good idea?
std::string
和 std::vector
已经定义了 operator<
:for strings and for vectors。所以我们可以将它们与 std::tie
一起使用来创建一个临时的 std::tuple
(它只使用对数据成员的引用,它不会创建任何副本,因此效率很高)以进行比较。
选项 1:提供 operator<
std::set
需要比较它的对象,以便它知道什么是唯一的以及如何对事物进行排序。默认情况下,它将通过使用 operator<
(通过 std::less
)来执行此操作,因此如果您为 class 提供该运算符,它将使用它。像这样:
struct data{
vector<string> att;
string ds;
operator<(const data& other) {
// Be sure to #include <tuple> for std::tie
return std::tie(att, ds) < std::tie(other.att, ds);
// If you don't want to (or can't) use std::tie, you can do this:
// return att < other.att || (att == other.att && ds < other.ds);
}
};
std::set<data> my_set; // Now it works.
选项 2:提供仿函数
这将使用 Compare
functor 来比较两个 data
对象(而不是 operator<
,因此我们不需要定义它):
struct Compare {
bool operator()(const data& left, const data& right) const {
return std::tie(left.att, left.ds) < std::tie(right.att, right.ds);
// Again, if you don't want to (or can't) use std::tie, you can do this:
// return left.att < right.att || (left.att == right.att && left.ds < right.ds);
}
};
std::set<data, Compare> my_set; // Now it works.
我已经声明了这样的结构:
struct data{
vector<string> att;
string ds;
};
现在一个集合来存储来自多个数据元素的唯一数据
set<data> s;
基于不同的vector<string> att
和string ds
如何操作?
在不知道您希望如何比较您的结构的情况下,您可以尝试以下操作:
struct data
{
vector<string> att;
string ds;
friend bool operator < (const data& lhs, const data& rhs)
{
if (std::lexicographical_compare(lhs.att.begin(), lhs.att.end(), rhs.att.begin(), rhs.att.end()))
{
return true;
}
else if (std::lexicographical_compare(rhs.att.begin(), rhs.att.end(), lhs.att.begin(), lhs.att.end()))
{
return false;
}
else
{
return lhs.ds < rhs.ds;
}
}
};
我对这个解决方案不满意,因为它执行了两次字典顺序比较,效率很低。希望有人能提出更好的解决方案。
基本思路是,对于每个成员,比较左 < 右。如果为真,则 return 为真,否则比较右 < 左。如果为真,return 为假。否则,继续下一个成员。
注意:您可以阅读更多关于我用来比较事物的技巧 (std::tie
) in Implementing comparison operators via 'tuple' and 'tie', a good idea?
std::string
和 std::vector
已经定义了 operator<
:for strings and for vectors。所以我们可以将它们与 std::tie
一起使用来创建一个临时的 std::tuple
(它只使用对数据成员的引用,它不会创建任何副本,因此效率很高)以进行比较。
选项 1:提供 operator<
std::set
需要比较它的对象,以便它知道什么是唯一的以及如何对事物进行排序。默认情况下,它将通过使用 operator<
(通过 std::less
)来执行此操作,因此如果您为 class 提供该运算符,它将使用它。像这样:
struct data{
vector<string> att;
string ds;
operator<(const data& other) {
// Be sure to #include <tuple> for std::tie
return std::tie(att, ds) < std::tie(other.att, ds);
// If you don't want to (or can't) use std::tie, you can do this:
// return att < other.att || (att == other.att && ds < other.ds);
}
};
std::set<data> my_set; // Now it works.
选项 2:提供仿函数
这将使用 Compare
functor 来比较两个 data
对象(而不是 operator<
,因此我们不需要定义它):
struct Compare {
bool operator()(const data& left, const data& right) const {
return std::tie(left.att, left.ds) < std::tie(right.att, right.ds);
// Again, if you don't want to (or can't) use std::tie, you can do this:
// return left.att < right.att || (left.att == right.att && left.ds < right.ds);
}
};
std::set<data, Compare> my_set; // Now it works.