【问题标题】:Is there a way to display cpp map in a specific way有没有办法以特定方式显示 cpp 图
【发布时间】:2021-07-04 23:53:10
【问题描述】:

我需要向用户显示以下座位并能够预订和取消预订。

class luxaryBus {
    public:
            std::map<std::string, int> seats{ {"1A", 0}, {"1B", 0}, {"1C", 0}, {"1D", 0},{"1E", 0},
                                        {"2A", 0}, {"2B", 0}, {"2C", 0}, {"2D", 0},{"2E", 0},
                                        {"3A", 0}, {"3B", 0}, {"3C", 0}, {"3D", 0},{"3E", 0},
                                        {"4A", 0}, {"44", 0}, {"4C", 0}, {"4D", 0},{"4E", 0},
                                        {"5A", 0}, {"5B", 0}, {"5C", 0}, {"5D", 0},{"5E", 0},
                                        {"6A", 0}, {"6B", 0}, {"6C", 0}, {"6D", 0},{"6E", 0},
                                        {"7A", 0}, {"7B", 0}, {"7C", 0}, {"7D", 0},{"7E", 0},
                                        {"8A", 0}, {"8B", 0}, {"8C", 0}, {"8D", 0},{"8E", 0},
                                        {"9A", 0}, {"9B", 0}, {"9C", 0}, {"9D", 0},{"9E", 0},
                                        {"10 A", 0}, {"10B", 0}, {"10C", 0}, {"10D", 0},{"10E", 0},
                                        {"11 A", 0}, {"11B", 0}};
    
    void displaySeats();
}



void luxaryBus::displaySeats()
{
int test = 0;
    for (const auto& p : this->seats) {
        if (test == 5) {
            std::cout << std::endl;
            test = 0;
        }
        test++;
        std::cout << p.first << p.second << "\t ";
    }
}

显然,它以一种对我不起作用的方式对字符串进行排序:

1A 10A 10B 10C 等...

我也尝试了 unordered_map,但无论我做什么,我都无法让地图以我想要的方式显示座位(1A、1B、1C、1D、1E)。

1A 1B 1C 1D 1E

2A 2B 2C 2D 2E ....

试图将座位名称更改为 A1 B1 C1 D1... 显然我是 C++ 新手。我知道地图是有序的。而且我知道使用 unordered_map 无法保证地图的显示方式。

我的问题是,我能否以特定方式使用地图,以便以我想要的方式显示它。或者,我可以在 C++ 中使用另一种数据结构来完成我的任务。

Array 是我的第一选择,但是,我发现很难跟踪哪个座位已售出并处理取消。现在我可以使用 2 个数组,一个用于字符串表示,一个用于处理预订和取消操作。

谁能给我建议如何解决这个问题?

【问题讨论】:

  • 请发帖minimal reproducible example。我们不需要全部 50 个座位。我们需要的是一个完整的可构建的可运行程序,它可以生成说明问题的输出。
  • 感谢您告诉我。我将编辑我的问题。

标签: c++ arrays dictionary hashmap


【解决方案1】:

您可以放入一个自定义比较器,以按照您想要的顺序对地图中的数据进行排序。

对此,可以参考以下代码:

    auto seatCompare = [](std::string const& seat1, std::string const& seat2) -> bool {
        std::smatch result1;
        std::smatch result2;
        std::regex pattern(R"(([0-9]+)([a-z A-Z]+))");
        if (!regex_match(seat1, result1, pattern) || !regex_match(seat2, result2, pattern)) {
            throw std::runtime_error("Seat name invalid!");
        }
        if (std::stoi(result1[1]) == std::stoi(result2[1])) {
            return result1[2] < result2[2];
        }
        return std::stoi(result1[1]) < std::stoi(result2[1]);
    };
    std::map<std::string, int, decltype(seatCompare)> seats(seatCompare);
    seats = { {"1A", 0}, {"1B", 0}, {"1C", 0}, {"1D", 0},{"1E", 0},
              {"2A", 0}, {"2B", 0}, {"2C", 0}, {"2D", 0},{"2E", 0},
              {"3A", 0}, {"3B", 0}, {"3C", 0}, {"3D", 0},{"3E", 0},
              {"4A", 0}, {"4B", 0}, {"4C", 0}, {"4D", 0},{"4E", 0},
              {"5A", 0}, {"5B", 0}, {"5C", 0}, {"5D", 0},{"5E", 0},
              {"6A", 0}, {"6B", 0}, {"6C", 0}, {"6D", 0},{"6E", 0},
              {"7A", 0}, {"7B", 0}, {"7C", 0}, {"7D", 0},{"7E", 0},
              {"8A", 0}, {"8B", 0}, {"8C", 0}, {"8D", 0},{"8E", 0},
              {"9A", 0}, {"9B", 0}, {"9C", 0}, {"9D", 0},{"9E", 0},
              {"10A", 0}, {"10B", 0}, {"10C", 0}, {"10D", 0},{"10E", 0},
              {"11A", 0}, {"11B", 0}};

或 C++98 风格

struct SeatCompare {
    bool operator()(std::string const& seat1, std::string const& seat2)
    {
        std::smatch result1;
        std::smatch result2;
        std::regex pattern(R"(([0-9]+)([a-z A-Z]+))");
        if (!regex_match(seat1, result1, pattern) || !regex_match(seat2, result2, pattern)) {
            throw std::runtime_error("Seat name invalid!");
        }
        if (std::stoi(result1[1]) == std::stoi(result2[1])) {
            return result1[2] < result2[2];
        }
        return std::stoi(result1[1]) < std::stoi(result2[1]);
    }
};

std::map<std::string, int, SeatCompare> seats{ 
    {"1A", 0}, {"1B", 0}, {"1C", 0}, {"1D", 0},{"1E", 0},
    {"2A", 0}, {"2B", 0}, {"2C", 0}, {"2D", 0},{"2E", 0},
    {"3A", 0}, {"3B", 0}, {"3C", 0}, {"3D", 0},{"3E", 0},
    {"4A", 0}, {"4B", 0}, {"4C", 0}, {"4D", 0},{"4E", 0},
    {"5A", 0}, {"5B", 0}, {"5C", 0}, {"5D", 0},{"5E", 0},
    {"6A", 0}, {"6B", 0}, {"6C", 0}, {"6D", 0},{"6E", 0},
    {"7A", 0}, {"7B", 0}, {"7C", 0}, {"7D", 0},{"7E", 0},
    {"8A", 0}, {"8B", 0}, {"8C", 0}, {"8D", 0},{"8E", 0},
    {"9A", 0}, {"9B", 0}, {"9C", 0}, {"9D", 0},{"9E", 0},
    {"10A", 0}, {"10B", 0}, {"10C", 0}, {"10D", 0},{"10E", 0},
    {"11A", 0}, {"11B", 0}};

【讨论】:

  • 也许我忘了提到,但这发生在类定义中。所以现在我上面的代码有几个错误。第一个 - auto is not allowed here。第二 - 'seatCompare': a non-static data member cannot have a type that contains 'auto'. 第三 - member "luxaryBus::seatCompare" is not a type name 第四 - more than one conversion function from "lambda []bool (const std::string &amp;seat1, const std::string &amp;seat2)-&gt;bool" to "&lt;error-type&gt;" applies.
  • 这有时被称为Natural sort order,它也有 C++ 库。
  • 很抱歉,我没有意识到你是 C++ 的新手,但是上面的样式只需稍作修改就可以放入类中,但既然你已经接受了最后一个答案,我懒得改了。@Noonewins
【解决方案2】:

std::map 使用比较 operator&lt; 来比较映射中的键。但是,问题在于字符串是按字典顺序比较的,所以"1A""10A" 都小于"1B"

但您可以使用更复杂的映射:std::map&lt;std::pair&lt;int, char&gt;, int&gt;,其中键是数字和字符。这里将数字作为数字进行比较,将字符作为字符进行比较。

像这样使用它:

std::map<std::pair<int, char>, int> map{{{1, 'B'}, 0}, {{1, 'C'}, 0}};

PS:你可以像这里一样覆盖输出:

std::ostream& operator<<(std::ostream& out, const std::map<std::pair<int, char>, int>& map)
{
    for (const auto& p : map) {
        out << p.first.first << p.first.second << " ";
    }
    return out;
}

int main() {
    std::map<std::pair<int, char>, int> map{{{1, 'B'}, 0}, {{1, 'C'}, 0}};

    std::cout << map;
    return 0;
}

【讨论】:

  • 这实际上是一个非常聪明的方法。谢谢!我现在将使用它。如果没有更好的编程方式,我会尽快将其标记为答案。
  • 不客气,@Noonewins,我想是时候结束这个问题了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-18
  • 1970-01-01
  • 2011-07-11
  • 1970-01-01
相关资源
最近更新 更多