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
类型排序,锁定它的顺序,然后第二个,......等等。看起来复杂而繁琐。有更好的方法吗?
答案 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)