我正在设置一个unordered_map,其中的键是Direction的枚举,定义为:
enum Direction : uint16_t {
North = 1 << 0,
East = 1 << 2,
South = 1 << 3,
West = 1 << 4,
None = 1 << 5,
};
字符串
目标是检查是否至少设置了这些标志中的2个,但最多设置了 *n个标志。
使用上面定义的枚举,我尝试创建一些unordered_map
std::unordered_map<Direction, std::vector<Tile*>>* groundTiles;
std::unordered_map<Direction, std::vector<Tile*>>* northEastHillTiles;
std::unordered_map<Direction, std::vector<Tile*>>* southEastHillTiles;
std::unordered_map<Direction, std::vector<Tile*>>* platformTiles;
std::unordered_map<Direction, std::vector<Tile*>>* wallTiles;
型
我将它们初始化为
groundTiles = new std::unordered_map<Direction, std::vector<Tile*>>();
groundTiles->insert_or_assign(Direction::None, std::vector<Tile*>());
groundTiles->insert_or_assign(Direction::East, std::vector<Tile*>());
groundTiles->insert_or_assign(Direction::West, std::vector<Tile*>());
groundTiles->insert_or_assign((Direction)(Direction::East|Direction::West),std::vector<Tile*>());
and so on for the other sets
型
然而,当我尝试从地面(或任何其他设置)拉一个瓷砖时,我无法检查是否至少设置了方向::东和方向::西。我试过:
Tile* westAndEastCapped = southEastHillTiles->at((Direction)(Direction::West | Direction::East)).at(0);
型
但它似乎只是默认为Direction::East集。
我如何从一个unordered_map中选择一个图块,同时设置了East和West标志,而没有其他标志?
2条答案
按热度按时间ar5n3qh51#
这不是
std::unordered_map::at()
的工作方式。它只从无序Map中检索与传入参数 * 相等 * 的键的值。相等的意思是“完全”。就这些。没别的了。此外,如果指定的键不存在,
at()
会抛出异常。std::unordered_map
只知道它的键是某种不透明的值。std::unordered_map
不关心键的任何解释或含义,除了std::unordered_map
对它的键的唯一要求是它有一个相等比较和它有一个散列函数。enum
符合这些要求。结束。仅仅因为这个特定的enum
被解释为某种类型的位掩码,对std::unordered_map
来说没有任何意义。std::unordered_map
不适合你试图访问它的值的方式,它不会工作。您可能需要为您的值设计一个自定义容器,以有效地实现所需的访问模式。在最坏的情况下,你总是可以求助于范围迭代:
字符串
然后检查Map中的每个当前
key
,以确定它是否符合您正在搜索的内容。这是非常低效的,但这几乎是unordered_map
唯一能做的事情。dauxcl2d2#
无序Map被设计成非常有效地找到对应于一个特定键值的元素。不幸的是,在你的问题中,你不知道你要找的键值。您只知道密钥必须满足的一些约束。
一种方法是遍历所有现有的键并检查它们是否与约束匹配。但它不是很有效率。
如果这些消耗性的搜索很频繁,并且如果你的map中的key相对稳定,你可以考虑预先计算研究:搜索Map会将每个元素
Direction
与包含此方向的键**set
相关联:考虑到你只有几个基本方向,你甚至可以预先计算每个可能组合的集合(因为方向东|西方不是很相关,组合学应该保持在控制之下)。
问题是,每一个新的关键字插入到你的瓷砖Map将需要重新计算搜索Map。但是你可以从源头上解决这个问题,并定义一个特殊的容器来提供所有这些功能:对于插入到该容器中的每个新的关键字和区块值,容器将更新用于查询的相关集合。
注意:如果你的Map非常动态,添加和删除了大量的键,或者键的数量可能会变得非常大,那么所提出的方法的效率增益可能会丢失。在这种情况下,您需要寻找不同的索引方案,例如**bitmap indexing**(或等效方案,例如某种trie-不是打字错误)。