【问题标题】:C++ Map : manipulate map inside mapC++ Map:在地图内操作地图
【发布时间】:2018-08-31 10:00:46
【问题描述】:

我更习惯于使用单个地图而不是嵌套地图。所以我很难理解如何处理这个问题。

备注:请不要要求我使用multimap或boost,我只能使用这种结构

在 C++ STL 映射中,我有这样的定义

map<string, map<string, string>> exploration; // country --> state --> city

第一张地图表示一对键(国家)和值作为树结构map&lt;string, string&gt;,分别代表各自的州和城市。

我知道如何手动填充此结构(硬编码),如下所示:

exploration["Canada"]["Ontario"] = "Toronto";

问题:

稍后上面显示的数据将由用户输入:

&gt; Canada Ontario Toronto

&gt; Canada Alberta Edmonton

&gt; USA Washington Seatle

&gt; USA Nevada Las-Vegas

所以如果我将这个逻辑应用到上面的示例中,这是错误的,因为 map 不接受重复的键

插图(错误)

exploration["Canada"]["Ontario"] = "Toronto";
exploration["Canada"]["Alberta"] = "Edmonton";

插图(我在找什么)

exploration["Canada"]["Ontario"] = "Toronto";
                     ["Alberta"] = "Edmonton";

        Canada
          **
         *  *     
        *    *
     Ontario Alberta
       *        *
      *          *
   Toronto     Edmonton  

我的假设解决方案,

> Canada Ontario Toronto

1个案例:如果勘探结构中不存在国家(加拿大),我将其与省和市一起添加。

2 case:如果国家(加拿大)存在,那么我把之前输入的数据加长边安大略和多伦多。

欢迎任何指示、想法或提示。

【问题讨论】:

  • 嗯,你写的错误插图实际上是正确的。它将为 Canada 键创建一个映射,其中包含另一个映射作为其值。后者则包含两个键。
  • 我觉得这个链接可能对你有帮助:cplusplus.com/forum/beginner/113056
  • “所以如果我将这个逻辑应用到我上面的例子中,这是错误的,因为 map 不接受重复的键”。您看到的实际问题是什么?编译错误?意外行为?
  • 我的意思是错误的意思是我不希望每次都插入加拿大的钥匙,而是在国家存在的情况下只插入内部地图

标签: c++ dictionary mapping nested-map


【解决方案1】:

你的例子很正确。查看下面的代码(在 C++11 中,但同样的推理适用于以前的版本),您可以看到每个国家/地区仅在 exploration 地图中插入一次。

代码:

#include <iostream>
#include <map>

using namespace std;

int main() {
    map<string, map <string, string> > exploration;
    exploration["Canada"]["Ontario"] = "Toronto";
    exploration["Canada"]["Alberta"] = "Edmonton";
    exploration["USA"]["Washington"] = "Seattle";
    exploration["USA"]["Nevada"] = "Las Vegas";

    cout << "Number of keys: " << exploration.size() << endl;

    for (auto country : exploration) {
        for (auto city : country.second)
            cout << country.first << ":" << city.first << " -> " << city.second << endl;
    }

    return 0;
}

输出:

Number of keys: 2
Canada:Alberta -> Edmonton
Canada:Ontario -> Toronto
USA:Nevada -> Las Vegas
USA:Washington -> Seattle

让我们一步一步来了解发生了什么:

  1. map&lt;string, map &lt;string, string&gt; &gt; exploration:定义一个键为字符串,值为其他映射的映射。到目前为止它是空的。
  2. exploration["Canada"]["Ontario"] = "Toronto":首先它检查Canadaexploration map 中不存在。因此创建了一个映射,将Canada 链接到一个空映射。现在,在 exploration["Canada"] 映射中创建了从 OntarioToronto 的映射。
  3. exploration["Canada"]["Alberta"] = "Edmonton":由于Canada键已经存在于exploration中,不需要再创建。它只会在已创建的地图中将Alberta 映射到Edmonton

同样的推理也适用于USA 映射。这样,即使使用嵌套映射也不会有重复的键。 C++ 很棒。

【讨论】:

  • 我需要创建另一个函数来验证加拿大(国家)是否存在,还是通过地图自动完成?
  • @DavidEdgar 不需要。当 C++ 检测到键不存在时,它会自动创建内部映射。我写的例子很完美。
  • 如果我想检查某个国家/地区是否存在特定城市,该怎么办。就像检查 fi 多伦多插入加拿大一样。如何处理?
  • Check this answer。您可以执行if (exploration["Canada"].find("Toronto") != exploration.end()) 之类的操作来检查Toronto 是否在Canada 内。
  • @MatheusPortela exploration["Canada"].end()
【解决方案2】:

你可以有两个城市在同一个州,所以你真的需要map&lt;string, map&lt;string, set&lt;string&gt;&gt;&gt;

但是你之前拥有的东西已经可以工作了。例如:

#include <iostream>
#include <map>
#include <set>
#include <string>

int main() {

    std::map<std::string, std::map<std::string, std::set<std::string>>> countries;

    countries["Canada"]["Ontario"].insert("Toronto");
    countries["Canada"]["Ontario"].insert("Something else");
    countries["Canada"]["Alberta"].insert("Edmonton");


    for (const auto& country : countries) {
        std::cout << "Country: " << country.first << "\n";
        for (const auto& statePair : country.second) {
            std::cout << "State: " << statePair.first << "\n";
            for (const auto& city : statePair.second) {
                std::cout << "City: " << city << "\n";
            }
        }
    }

    return 0;
}

会输出

Country: Canada
State: Alberta
City: Edmonton 
State: Ontario
City: Something else
City: Toronto

编辑:

关于您的后续问题,这应该可以帮助您:

using CountryMap = std::map<std::string, std::map<std::string, std::set<std::string>>>;
bool countryContainsCity(const CountryMap& countryMap, const std::string& country, const std::string& city)
{
    for (const auto& country : countryMap[country]) {
        for (const auto& statePair : country.second) {
            if (statePair.second.find(city)
            {
                return true;
            }
        }
    }

    return false;
}

【讨论】:

  • 如果以防万一,我想检查某个国家(加拿大)是否存在名为多伦多的城市。如何处理?
  • 好@dempzorz,我稍后会尝试+1
猜你喜欢
  • 1970-01-01
  • 2023-04-10
  • 2019-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多