如何删除存储在 std::map 中的 std::set 中的元素?

How do I delete elements from an std::set that is stored inside a std::map?

我将以下数据结构存储在 class.

class MyClass {
 private:
  std::map<std::string, std::set<std::string>> myMap;
 public:
  void remove(std::string id); //trying to remove items from sets inside myMap
}

然后有一种方法可以尝试从集合中删除项目。我尝试了以下两种方法,但均无效。方法 1,使用 for 范围。

for (auto pair : myMap) {
 auto set = pair.second;
 if (set.count(id)) {
  set.erase(id);
 }
}

方法二,使用iterator.

auto it = myMap.begin();
while (it != myMap.end()) {
 auto set = it->second;
 if (set.count(id)) {
  set.erase(id);
 }
 it++;
}

在 C++ 中从映射中的集合中删除元素的正确方法是什么?请注意,当我将 myMap 定义为 std::map<std::string, std::set<std::string>*>(指针)时,我的代码可以正常工作。

假设我们有这样一个std::map

std::map<std::string, std::set<std::string>> myMap;
myMap["a"].insert("aaa");
myMap["a"].insert("abb");
myMap["a"].insert("acc");

myMap["b"].insert("aaa");
myMap["b"].insert("abb");
myMap["b"].insert("acc");

然后您可以通过执行以下操作从 std::set 中删除项目:

for (auto& i : myMap) {
    i.second.erase("aaa");
}

Demo

为什么问题的方法不起作用?

因为,通过执行以下 for(auto pair : myMap) {...}auto set = pair.second;,您实际上是在处理来自 myMap 的数据副本。因此,您需要使用对实际数据的引用,例如 for(auto& pair : myMap) {...}auto& set = pair.second;.

此外,如果存在std::set::erase会从std::set中删除数据,因此不需要手动检查 id 是否存在。

您正在复制要变异的对象。看来你有 Java 的背景。在 C++ 中,如果你想要引用语义(而不是值语义),你应该使用引用(auto & 而不是 auto 在这种情况下)。操作方法如下:

#include <algorithm>
#include <map>
#include <set>
#include <string>

class MyClass {
 private:
  std::map<std::string, std::set<std::string>> myMap;

 public:
  void remove(std::string const& id) {
    std::for_each(myMap.begin(), myMap.end(),
                  [&id](auto& p) { p.second.erase(id); });
  }
};