在C ++中实现类似SQL的顺序

时间:2016-09-08 12:16:51

标签: c++

c ++中是否有算法按多列排序?或者像SQL这样的其他方式以非常简单的方式进行,ORDER BY <>,<>?例如,给定SQL SillyData表:

Name   Age  FavouriteFruet LuckyNumber
--------------------------------------
Mary   22   Apple          2
Alice  22   Banana         7
Bob    21   Orange         8
Mark   21   Apple          0
John   22   Banana         3

当我这样做的时候 SELECT * FROM SillyData ORDER BY Age, FavouriteFruet, LuckyNumber这就是结果:

Name   Age  FavouriteFruet LuckyNumber
--------------------------------------
Mark   21   Apple          0
Bob    21   Orange         8
Mary   22   Apple          2
John   22   Banana         3
Alice  22   Banana         7

我能想到的只是list tuple。但后来我必须按第一个tuple类型排序,锁定它的顺序,然后第二个,......等等。看起来复杂而繁琐。有更好的方法吗?

3 个答案:

答案 0 :(得分:3)

假设您希望对字符串进行不区分大小写的比较,这是一个起点:

#include <tuple>
#include <string>
#include <iostream>
#include <cstring>
#include <functional>

struct row
{
    std::string Name;
    int Age;
    std::string FavouriteFruet;
    int LuckyNumber;
};

auto index_order(const row& r)
{
    auto as_upper = [](std::string s)
    {
        std::transform(s.begin(), s.end(), s.begin(), [](auto c){return std::toupper(c); });
        return s;
    };
    return std::make_tuple(std::cref(r.Age), as_upper(r.FavouriteFruet), std::cref(r.LuckyNumber), as_upper(r.Name));
}

int main()
{
    std::vector<row> results =
    {
        { "Mary", 22, "Apple", 2},
        { "Alice", 22, "Banana", 7},
        { "Bob", 21, "Orange", 8},
        { "Mark", 21, "Apple", 0},
        { "John", 22, "Banana", 3},
    };

    std::sort(results.begin(), results.end(),
              [](auto const& l, auto const& r)
              {
                  return index_order(l) < index_order(r);
              });

    for (auto const& r : results)
    {
        std::cout << r.Name << " | " << r.Age << " | " << r.FavouriteFruet << " | " << r.LuckyNumber << '\n';
    }    
}

预期产出:

Mark | 21 | Apple | 0
Bob | 21 | Orange | 8
Mary | 22 | Apple | 2
John | 22 | Banana | 3
Alice | 22 | Banana | 7

答案 1 :(得分:1)

您可以使用std::stable_sort。例如,我为类型info定义了不同的单独排序函数,并将它们与std::stable_sort一起使用,以实现我想要的任何相对排序:

struct info
{
    std::string name;
    int age;
    std::string fav_fruit;
    int fav_number;

    // static functions define sorting methods
    static bool sort_by_name(info const& lhs, info const& rhs)
    {
        return lhs.name < rhs.name;
    }

    static bool sort_by_age(info const& lhs, info const& rhs)
    {
        return lhs.age < rhs.age;
    }

    static bool sort_by_fav_fruit(info const& lhs, info const& rhs)
    {
        return lhs.fav_fruit < rhs.fav_fruit;
    }

    static bool sort_by_fav_number(info const& lhs, info const& rhs)
    {
        return lhs.fav_number < rhs.fav_number;
    }

    // friend function provides output operator
    friend std::ostream& operator<<(std::ostream& os, info const& i)
    {
        return os << i.name << '\t' << i.age << '\t' << i.fav_fruit << '\t' << i.fav_number;
    }
};

int main()
{

    std::vector<info> infos
    {
        {"Mary",  22, "Apple",  2},
        {"Alice", 22, "Banana", 7},
        {"Bob",   21, "Orange", 8},
        {"Mark",  21, "Apple",  0},
        {"John",  22, "Banana", 3},
    };

    // std::stable_sort will not rearrange the currently sorted order
    // of items that are otherwise considered equal in terms of the current
    // sort condition

    // NOTE: We sort them in reverse order of importance, the most significant
    // ordering being the last one imposed

    std::stable_sort(infos.begin(), infos.end(), info::sort_by_fav_number);
    std::stable_sort(infos.begin(), infos.end(), info::sort_by_fav_fruit);
    std::stable_sort(infos.begin(), infos.end(), info::sort_by_age);

    std::cout << "Name\tAge\tFruit\tNumber" << '\n';
    std::cout << "----\t---\t-----\t------" << '\n';

    for(auto i: infos)
        std::cout << i << '\n';
}

<强>输出:

Name    Age Fruit   Number
----    --- -----   ------
Mark    21  Apple   0
Bob     21  Orange  8
Mary    22  Apple   2
John    22  Banana  3
Alice   22  Banana  7

答案 2 :(得分:0)

您可能需要一些lexicographical order

因此,使用std::lexicographical_compare可能会传递给某些std::sort作为比较测试。

(我希望你至少使用C ++ 11)