C++ 在结构上实现 ORDER BY
C++ implementation of ORDER BY on struct
我在这里和其他网站上搜索了很多,但我没有找到令人满意的东西。
我需要的是非常简单的任务 - 基本上是在 C++ 中构造 ORDER BY 运算符。 这意味着我有具有许多不同数据类型成员的结构,并且我需要一个具有可配置成员和排序的比较器。 这是我的伪代码想法:
comparator.add(&MyStruct::member1, std::less);
comparator.add(&MyStruct::member2, std::greater);
std::sort(my_vector.begin(), my_vector.end(), comparator);
我得到按成员 1 排序的数据,如果它相等,成员 2 决定,依此类推。
我在 STL 和模板方面不太好,但我可以阅读和破译一些代码,并发现这是非常合适的解决方案:https://stackoverflow.com/a/11167563
不幸的是,在我的工作中,我不得不使用带有错误的 32 位编译器的 C++ 构建器,该编译器拒绝编译此正确的代码。 它几乎不支持C ++ 11,它有可用的Boost 1.39。
是否有人有任何解决方案可以在我的可用资源下为我工作? 提前谢谢你
编辑:
我得到了非常专业的解决方案,其中包含我知道的硬编写的比较运算符,并且在这里效果不佳。 我在我的问题中错过了这一点。 我的结构至少有 15 个成员,正如我所写,我需要经常更改成员/列的单个排序方向(ASC、DESC)。 同样,我需要经常更改排序成员的集合, 例如,就像 SQL 中按运算符排序一样。我也不能使用类似stable_sort的东西,因为我只是在为某个类的 OnCompare 事件之类的东西编写比较器。
这并不难。 首先,考虑"规范"排序关系:
struct Compare
{
bool operator()( C const& lhs, C const& rhs ) const
{
return lhs.a < rhs.a
|| ( !(rhs.a < lhs.a) && lsh.b < rhs.b )
|| ( !(rhs.a < lhs.a) && !(rhs.b < lhs.b) && lhs.c < rhs .c )
|| ...
}
};
显然,没有人会真正写这样的东西,但是它完全符合什么是需要。
当然,如果我们能将数据成员想象成一个数组,我们可以将其重写为循环,利用以前的每种情况下的既定!(rhs[i-1] < lsh[i-1]
:
struct Compare
{
bool operator()( C const& lhs, C const& rhs ) const
{
int i = 0;
while ( i != N && !(lhs[i] < rhs[i]) && !(rhs[i] < lhs[i]) ) {
++ i;
}
return i != N && lhs[i] < rhs[i];
}
};
或者,如果所有元素都是完全有序的,则==
也在它们上定义,我们可以假设它对应于弱部分建立的等价关系订购:
struct Compare
{
bool operator()( C const& lhs, C const& rhs ) const
{
int i = 0;
while ( i != N && !(lhs[i] == rhs[i]) ) {
++ i;
}
return i != N && lhs[i] < rhs[i];
}
};
剩下的就是以某种方式将其转化为某种东西可以处理任意元素的任意顺序类型。 有句老话说,解决所有问题是额外的间接级别,它适用于此处。
首先,我们需要一些处理不同类型的每个元素。 多态性似乎是合适的(尽管如果按顺序使模板工作在编译时修复了评估的元素):
struct CompareOneElementOfC
{
virtual bool isLessThan( C const& lhs, C const& rhs) const = 0;
virtual bool isEqual( C const& lhs, C const& rhs) const = 0;
};
template <typename T, T C::*ptr>
struct ConcreteCompareOneElementOfC : public CompareOneElementOfC
{
virtual bool isLessThan( C const& lhs, C const& rhs) const
{
return lhs.*ptr < rhs.*ptr;
}
virtual bool isEqual( C const& lhs, C const& rhs) const
{
return lhs.*ptr == rhs.*ptr;
}
};
根据元素的类型,您可能需要手动操作编写具体的实例。 如果有任何元素不支持总排序,您必须省略 isEqual
,并相应地修改以下代码。
到目前为止,我们只需要每个静态实例的一个静态实例具体比较:
ConcreteCompareOneElementOfC<int, &C::a> const c1;
ConcreteCompareOneElementOfC<double, &C::b> const c2;
// ...
最后,将这些实例的地址放在一个表中:
CompareOneElementOfC const* const cmp[] = { &c1, &c2 ... };
您可以为不同的顺序使用不同的表。 如果有只有几个,为每个定义静态表,并完成它。 如果排序可以是任意的,请在在每次排序之前,按所需的顺序飞行。
最后:
class Compare
{
CompareOneElementOfC const* const* begin;
CompareOneElementOfC const* const* end;
public:
template< size_t N >
Compare( CompareOneElementOfC const* const (&cmp)[N] )
: begin( cmp )
, end( cmp + N )
{
}
bool
operator()( C const& lhs, C const& rhs ) const
{
auto current = begin;
while ( current != end && (*current)->isEqual( lhs, rhs ) ) {
++ current;
}
return current != end && (*current)->isLessThan( lhs, rhs );
}
}
(请注意,我还没有实际测试过这段代码,所以有可能是错别字和其他错误。 尽管如此,基本思想应该在那里。
我认为只是重载operator <
对您有用。
struct Struct {
int member1;
int member2;
bool operator<(const Struct& rhs) const {
if (member1 != rhs.member1)
return member1 < rhs.member1
else
return member2 > rhs.member2
}
};
这样,每当比较任何 2 个Struct
实例时,它们都将通过 operator <
中定义的比较函数进行比较。
因此,一个简单的std::sort(vec.begin(), vec.end())
就可以了!
编辑:
否则,您始终可以定义一个可用于比较每个元素的函子。这只是一个具有重载operator ()
用于比较的类。
class ComparisonClass {
public:
bool operator()(const Struct& lhs, const Struct& rhs) {
if (lhs.member1 != rhs.member1)
return lhs.member1 < rhs.member1
else
return lhs.member2 > rhs.member2
}
};
您还可以定义ComparisonClass
的一些成员值,这些值定义比较的顺序。
使用它就像这样称呼它std::sort(vec.begin(), vec.end(), ComparisonClass());
编辑2:
稍微复杂的代码 -
class ComparisonClass {
public:
bool operator()(const Struct& lhs, const Struct& rhs) {
for(int i=0; i<m_comparisonOrder.size(); i++) {
int pos = m_comparisonOrder[i];
if (lhs[pos] != rhs[pos]) {
if (m_comparisonType[pos])
return lhs[pos] < rhs[pos];
else
return lhs[pos] > rhs[pos];
}
}
}
std::vector<int> m_comparisonOrder.
std::vector<bool> m_comparisonType;
};
在这里,我假设Struct
有一个返回相应成员变量的operator []
。
为什么不有一个专门的比较器功能,首先检查member1
,如果相等,则检查member2
?
喜欢
bool comparator(const MyStruct& s1, const MyStruct& s2)
{
if (s1.member1 == s2.member1)
return s1.member2 > s2.member2;
else
return s1.member1 < s2.member1;
}
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- Ascending order c++
- 将 std::thread by 值推送到列表中
- 如何处理Boost Spirit X3导致Visual Studio 2019 "static initialization order fiasco"?
- MATLAB to C++: csvread() not supported by MATLAB Coder
- Makefile by ocaml 和 cpp 扩展名
- C++ OpenCV Randu 函数抛出'Integer division by zero'
- 从函数 BY VALUE 返回数组,返回结构时会发生什么?
- 如何在不受其他文件影响的情况下"by itself" Visual Studio 项目中运行C++文件?
- "static initialization order fiasco"是 constexpr 变量的问题吗?
- 在使用 In Order 遍历成员函数时引发异常(堆栈溢出)时出现问题
- MacPorts:"Error: clang-4.0 has been replaced by clang-8.0; please install that instead",但我已经安装了clang
- 为什么 c++ 向量没有"delete by index"?
- 这个给定的代码应该将给定的数字转换为尽可能滞后的数字,no.by 用 9.It 替换合适的数字是行不通的
- 传递类 by-value 时,调用方或被调用方是否调用析构函数
- By-ref 参数:这是 std::thread 和 std::bind 之间的不一致吗?
- 为什么在与静态库链接时强制执行 order(例如 source.cxx -lstatic)
- 转到特定页面后,如何将滑动视图的当前索引设置为选项卡栏"by reference"的当前索引?
- base64 decode with openssl BIO block by block
- C++ 在结构上实现 ORDER BY