2015-06-17 95 views
2

在我的假設應用程序中,我從服務器收到酒店列表。根據字符串變量設置的規則進行排序

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") ... 

我使用Qt 5.4一起使用C++ 11。沒有提升。

+0

你打算用你的結構變量做結構數組嗎? – bobtheboy

+0

@bobtheboy我認爲沒有。我只是試圖給出一個通用的例子。實際上,我有一組具有提供諸如「int stars()」,「int freeRoomCount()」和「int parkingPlacesAvailable()」之類的接口的類。當我用這些類填充UI列表視圖時,我應該依賴「std :: string」排序規則。 – Dalamber

+0

你可以使用std :: sort嗎? http://www.cplusplus.com/reference/algorithm/sort/展示瞭如何使用比較函數,並且可以在那裏使用排序規則字符串。 – donjuedo

回答

2

你可以自己選擇和函子來排序之間的映射,例如

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

輸出將是(working demo

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函數。

+0

非常感謝你們。我喜歡這個C++ 11解決方案! – Dalamber

3

我會用一個簡單的解析器來讀取一個字符,將一個std::stable_sort與字符的關聯比較謂詞應用,然後進入下一個字符。

stable_sort部分非常重要。這意味着如果您先按星號對項目進行排序,然後按停車位排序,則星號的數量將保持不變。

+1

我也是這麼做的。所有你需要的是一個基於單個字符代碼的開關如何排序的功能;你可能會考慮做第一類不穩定的可能的優化(如果你經常按一個鍵排序,或者如果有很多重複的鍵) –

相關問題