根据字符串变量设置的规则进行排序

Sorting based on the rules set by a string variable

本文关键字:规则 排序 设置 字符串 变量      更新时间:2023-10-16

在我的假设应用程序中,我从服务器收到酒店列表。

struct Hotel 
{
  std::string name;            // e.g. Hilton, Ritz
  int stars;                   // In range [0..5], 0 stands for "unrated"
  int freeRoomCount;           // Number of available rooms [0..N]
  int parkingPlacesAvailable;  // Number of parking places availalble [0..M]
}
std::vector<Hotel> hotels;

所有这些项目都显示在一个简单的列表视图中。
我必须提供不同类型的排序。排序规则也由中央服务器决定。

排序规则如下:

std::string sortingRules; 
// "s" - sort by stars count
// "f" - sort by free room count
// "p" - sort by parking places available
// The sortingRules string can be a combination of those values. E.g.:
// "ps" - first goes who has the most number of parking places available, 
//        then goes hotels who has more stars
// More combinations available:
//  "s", "sf", "fp", "pf", "spf", "" etc. 
// (16 possible combinations, the empty string means alphabetical sorting)

所以问题是:如何用C++来解释这一点?枚举和位掩码值不起作用,因为它们不提供"顺序"控件。

我很好奇社区将如何解决此类任务?我觉得有一种方法可以解决此类问题,这就是为什么我不想直截了当地编写以下代码:

if (sortingRules[0] == "s") ...

我正在使用C++11和Qt 5.4。没有提升。

我会使用一个简单的解析器来读取一个字符,应用带有字符关联比较谓词的std::stable_sort,然后继续下一个字符。

stable_sort部分非常重要。这意味着,如果您先按星数排序项目,然后按停车位对项目进行排序,则星数的顺序将保持不变。

例如,您可以在他们的选择和要排序的函子之间创建一个映射

using SortFun = bool(*)(Hotel const&, Hotel const&);
std::map<char, SortFun> sorters {
    {'s', [](Hotel const& lhs, Hotel const& rhs){ return lhs.stars < rhs.stars; }},
    {'f', [](Hotel const& lhs, Hotel const& rhs){ return lhs.freeRoomCount < rhs.freeRoomCount; }},
    {'p', [](Hotel const& lhs, Hotel const& rhs){ return lhs.parkingPlacesAvailable < rhs.parkingPlacesAvailable; }}
};
然后,

您可以通过要求用户输入排序条件键来使用它,然后您可以使用 std::stable_sort 查找要排序的正确 lambda 。对于排序标准的组合,例如 "ps",您可以遍历每个排序键,并以相反的顺序连续std::stable_sort

int main()
{
    using SortFun = bool(*)(Hotel const&, Hotel const&);
    std::map<char, SortFun> sorters {
        {'s', [](Hotel const& lhs, Hotel const& rhs){ return lhs.stars < rhs.stars; }},
        {'f', [](Hotel const& lhs, Hotel const& rhs){ return lhs.freeRoomCount < rhs.freeRoomCount; }},
        {'p', [](Hotel const& lhs, Hotel const& rhs){ return lhs.parkingPlacesAvailable < rhs.parkingPlacesAvailable; }}
    };
    std::vector<Hotel> hotels {{"foo", 5, 4, 10},
                               {"bar", 3, 8, 20},
                               {"baz", 4, 5, 15},
                               {"fab", 3, 6, 18}};
    std::string choice;
    std::cout << "Pick a sort criteria s, f, p: ";
    std::cin >> choice;
    for (auto rit = choice.rbegin(); rit != choice.rend(); ++rit)
    {
        auto match = sorters.find(*rit);
        if (match != sorters.end())
        {
            std::stable_sort(begin(hotels), end(hotels), match->second);
        }
    }
    for(auto const& hotel : hotels)
    {
        std::cout << "Name: " << hotel.name << " Stars: " << hotel.stars << " Rooms: " << hotel.freeRoomCount << " Parking: " << hotel.parkingPlacesAvailable << std::endl;
    }
}

输出将是(工作演示)

Pick a sort criteria s, f, p: sf
Name: fab Stars: 3 Rooms: 6 Parking: 18
Name: bar Stars: 3 Rooms: 8 Parking: 20
Name: baz Stars: 4 Rooms: 5 Parking: 15
Name: foo Stars: 5 Rooms: 4 Parking: 10

要从最高到最低排序,只需在 lambda 函数中将所有<切换到>即可。