1

我将以下数据结构存储在一个类中。

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
}

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

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

方法 2,使用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>*>(指针)时,我的代码曾经可以工作。

4

2 回答 2

2

假设我们有一个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");
}

演示

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

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

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

于 2020-02-22T15:50:17.217 回答
1

您正在复制要变异的对象。看起来你有 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); });
  }
};
于 2020-02-22T15:52:56.383 回答