C++ C++;ORDER BY在结构上的实现
我在这里和其他网站上搜索了很多,但没有找到令人满意的东西C++ C++;ORDER BY在结构上的实现,c++,sorting,boost,stl,compare,C++,Sorting,Boost,Stl,Compare,我在这里和其他网站上搜索了很多,但没有找到令人满意的东西 我需要的是一个非常简单的任务——基本上由C++中的运算符构造顺序。这意味着我有一个包含许多不同数据类型成员的struct,我需要一个比较器来配置它的成员和顺序。以下是我的伪代码想法: comparator.add(&MyStruct::member1, std::less); comparator.add(&MyStruct::member2, std::greater); std::sort(my_vector.begi
我需要的是一个非常简单的任务——基本上由C++中的运算符构造顺序。这意味着我有一个包含许多不同数据类型成员的struct,我需要一个比较器来配置它的成员和顺序。以下是我的伪代码想法:
comparator.add(&MyStruct::member1, std::less);
comparator.add(&MyStruct::member2, std::greater);
std::sort(my_vector.begin(), my_vector.end(), comparator);
我得到按member1排序的数据,如果它等于member2,则由member2决定,依此类推
我不太擅长stl和模板,但我可以阅读和破译一些代码,并发现这是非常合适的解决方案:
遗憾的是,在我的工作中,我必须使用C++ Builder,而错误的32位编译器拒绝编译这个正确的代码。是的,它有boost 1.39可用
有没有人有任何解决方案可以在我的资源可用的情况下为我工作?先谢谢你
编辑:
我得到了非常专业的解决方案,使用了我所知道的硬编写的比较运算符,但在这里效果不太好。我的问题中没有提到这一点。我的结构至少有15个成员,正如我所写的,我需要经常更改成员/列(asc、desc)的单独排序方向。同样,我需要经常更改已排序成员集,就像sql中的order by运算符一样。此外,我不能使用稳定排序之类的东西,因为我只是在为某个类的OnCompare事件之类的东西编写比较器。为什么不使用一个专门的比较器函数,它首先检查
成员1
,如果相等,则检查成员2
像
bool比较器(const-MyStruct&s1,const-MyStruct&s2)
{
if(s1.member1==s2.member1)
返回s1.member2>s2.member2;
其他的
返回s1.member1
我认为仅仅重载操作符并不太难。首先,考虑“规范”。
订购关系:
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 )
|| ...
}
};
剩下的就是以某种方式将其转化为某种东西
它可以处理任意元素的任意顺序
类型。有句老话说,解决每一个问题
是一个额外的间接层次,它适用于这里
首先,我们需要一些方法来处理不同类型的问题
每个元素。多态性似乎是合适的(尽管
如果模板的顺序
评估的元素在编译时固定):
最后,将这些实例的地址放入表中:
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 );
}
}
类比较
{
比较元素常量*常量*开始;
比较元素常量*常量*结束;
公众:
模板
比较(CompareOneElementOfC常量*常量(&cmp)[N])
:开始(cmp)
,结束(cmp+N)
{
}
布尔
运算符()(C常量和左侧、C常量和右侧)常量
{
自动电流=开始;
while(current!=end&(*current)->isEqual(左侧、右侧)){
++电流;
}
返回电流!=结束和(*当前)->小于(左侧、右侧)的孤岛;
}
}
(请注意,我还没有实际测试这段代码,所以
可能是打字错误和其他错误。不过,基本的想法
“它几乎不支持c++11中的任何东西”-太糟糕了,一个具有元组魔力的lambda可以在这里创造奇迹。但是boost 1.39可能有元组(尤其是tie
函数)。谢谢这是一个很好的解决方案,而且很有效。然而,它能确定某个地方(在模板中或作为参数)也有比较函数吗?例如,我在delphi CompareText中使用了for string,在其他类型中使用了std::greater等等。对不起,我试着自己想:)我认为这应该可以使用简单的重载函数,如果我是,请纠正我wrong@blizzard如果实现的表单只使用了少于的函数,则可以用简单函数替换函数对象,而不是功能对象;函数对象的优点是它支持两个独立的函数,一个用于排序,另一个用于相等。(另一个可能的优势是,它可以保存额外的数据,以某种方式控制比较。这通常不是很有用,但在某些情况下可能有用。)@blizzard当然,用额外的参数或数据成员扩展模板没有问题,或者(正如我提到的)针对具体案例使用手写比较。该模板更多的是作为一个示例,而不是一个独特的解决方案。谢谢,我已经这样做了(扩展排序方向等)。
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 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 )
|| ...
}
};
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;
}
};
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 );
}
}