简体   繁体   English

结构上的ORDER BY的C ++实现

[英]C++ implementation of ORDER BY on struct

i searched a lot here and on other sites as well but i have not found something satisfying. 我在这里和其他网站上搜索了很多,但我还没有找到令人满意的东西。

what i need is quite simple task - substantially to construct ORDER BY operator in c++. 我需要的是一个非常简单的任务 - 基本上在c ++中构造ORDER BY运算符。 this means i have struct with a number of various data type members and i need a comparator for it with members and orderings configurable. 这意味着我有多个不同数据类型成员的结构,我需要一个比较器,成员和订单可配置。 here is my pseudocode idea: 这是我的伪代码想法:

comparator.add(&MyStruct::member1, std::less);
comparator.add(&MyStruct::member2, std::greater);
std::sort(my_vector.begin(), my_vector.end(), comparator);

and i get data sorted by member1 and if it is equal member2 decides, and so on. 我得到按member1排序的数据,如果它是等于member2决定,依此类推。

i am not too good in stl and templates, but i can read and decipher some code and found this as very appropriate solution: https://stackoverflow.com/a/11167563 我在stl和模板方面不太好,但我可以阅读并破译一些代码并发现这是非常合适的解决方案: https//stackoverflow.com/a/11167563

unfortunately in my work i have to use c++ builder with faulty 32bit compiler that refuses to compile this correct code. 不幸的是,在我的工作中,我必须使用带有错误的32位编译器的c ++ builder,拒绝编译这个正确的代码。 it does support almost nothing from c++11 , it has boost 1.39 available. 几乎没有支持c ++ 11 ,它提升了1.39。

does someone have any solution that could work for me with my resources available? 有没有人可以使用我的资源为我提供任何解决方案? thank you in advance 先感谢您

EDIT: 编辑:

i got very specialised solutions with hard-written comparison operators which i am aware of and which do not work here too good. 我得到了非常专业的解决方案,其中包含我所知道的难以编写的比较运算符,这些运算符在这里工作得不太好。 i missed this in my question. 我在我的问题中错过了这个。 my struct has at least 15 members and as i wrote, i need to often change individual sort directions for members/columns (asc, desc). 我的结构至少有15个成员,正如我写的,我需要经常更改成员/列的单独排序方向(asc,desc)。 too, i need to often change set of sorted members, just like in order by operator in sql, for example. 我也需要经常更改已排序成员的集合,就像在sql中按运算符顺序一样。 also i cannot use something like stable_sort as i am just writing comparator for something like OnCompare event of some class. 我也不能使用类似stable_sort的东西,因为我只是为某些类的OnCompare事件编写比较器。

It's not too difficult. 这不是太困难。 First, consider the "canonical" ordering relationship: 首先,考虑“规范”排序关系:

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 )
            || ...
    }
};

Obviously, no one would actually write something like this, but it corresponds exactly to the formal definition of what is needed. 显然,没有人会写这样的东西,但它完全符合所需要的正式定义。

Of course, if we can imagine the data members as an array, we could rewrite this as a loop, taking advantage of the previously established !(rhs[i-1] < lsh[i-1] in each case: 当然,如果我们可以将数据成员想象成一个数组,我们可以将其重写为一个循环,利用之前建立的!(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];
    }
};

Or, if all of the elements are fully ordered, so that == is also defined on them, and we can assume that it corresponds to the equivalence relationship established by the weak partial ordering: 或者,如果所有元素都是完全有序的,那么==也在它们上定义,我们可以假设它对应于弱偏序所建立的等价关系:

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];
    }
};

All that remains is to somehow translate this into something that can process an arbitrary ordering of elements of arbitrary types. 剩下的就是以某种方式将其转换为可以处理任意类型元素的任意排序的东西。 There's an old saying that the solution to every problem is an additional level of indirection, and it applies here. 有句老话说,每个问题的解决方案都是一个额外的间接层,它适用于此。

First, we need some means of handling the different types of each element. 首先,我们需要一些处理每个元素的不同类型的方法。 Polymorphism seems appropriate (although templates could be made to work if the order in which the elements were evaluated were fixed at compile time): 多态性似乎是合适的(尽管如果在编译时修改了元素的顺序,模板可以工作):

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;
    }
};

Depending on the types of the elements, you may need to hand write specific concrete instances. 根据元素的类型,您可能需要手动编写特定的具体实例。 And if any of the elements doesn't support total ordering, you will have to omit the isEqual , and modify the following code accordingly. 如果任何元素不支持总排序,则必须省略isEqual ,并相应地修改以下代码。

Having got this far, we need exactly one static instance of each concrete Compare: 到目前为止,我们需要每个具体的一个静态实例比较:

ConcreteCompareOneElementOfC<int, &C::a> const c1;
ConcreteCompareOneElementOfC<double, &C::b> const c2;
//  ...

Finally, put the addresses of these instances in a table: 最后,将这些实例的地址放在表中:

CompareOneElementOfC const* const cmp[] = { &c1, &c2 ... };

You can have different tables for different orderings. 您可以为不同的排序设置不同的表。 If there are only a few, define static tables for each, and be done with it. 如果只有少数,为每个定义静态表,并完成它。 If the orderings can be arbitrary, create the table on the fly before each sort, in the desired order. 如果排序可以是任意的,则在每次排序之前按所需顺序动态创建表。

Finally: 最后:

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 );
    }
}

(Please note that I haven't actually tested this code, so there are probably typos and other errors. Still, the basic idea should be there.) (请注意,我实际上没有测试过这段代码,所以可能存在拼写错误和其他错误。但是,基本的想法应该在那里。)

I think just overloading operator < will work for you. 我认为只是重载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
    }
};

This way whenever any 2 instances of Struct are compared, they will be compared by the comparison function defined in operator < . 这样,只要比较任何2个Struct实例,它们将通过operator <定义的比较函数进行比较。

So a simple std::sort(vec.begin(), vec.end()) will just work! 所以一个简单的std::sort(vec.begin(), vec.end())就可以了!

EDIT: 编辑:

Otherwise you can always define a functor which can be used to compare each element. 否则,您始终可以定义一个可用于比较每个元素的仿函数。 This is just a class with an overloaded operator () which is used for comparison. 这只是一个带有重载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
    }
};

You can additionally define some member values of the ComparisonClass which define the order of comparisons. 您还可以定义ComparisonClass一些成员值,这些成员值定义ComparisonClass的顺序。

Using it would be calling it like so std::sort(vec.begin(), vec.end(), ComparisonClass()); 使用它就像调用它一样std::sort(vec.begin(), vec.end(), ComparisonClass());

EDIT2: EDIT2:

Slightly more elaborate code - 稍微复杂的代码 -

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;
};

Here I'm assuming that Struct has an operator [] which returns the appropriate member variable. 这里我假设Struct有一个operator [] ,它返回相应的成员变量。

Why not have a specialized comparator function which first checks member1 and if equal then checks member2 ? 为什么没有专门的比较器函数,首先检查member1 ,如果相等则检查member2

Like 喜欢

bool comparator(const MyStruct& s1, const MyStruct& s2)
{
    if (s1.member1 == s2.member1)
        return s1.member2 > s2.member2;
    else
        return s1.member1 < s2.member1;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM