C++:从std :: map中按键弹出元素

10

我想要从一个map中删除具有特定键的元素,并使用这个元素。

您需要编写以下代码:

itr = MyMap.pop(wantedKey);
//Now MyMap is missing the element which has the key 'wantedKey'.
//Do something with this element through 'itr'.

有没有适用于这种情况的STL映射方法?

编辑

根据carleeto的回复,我想澄清一下:我需要从地图中删除元素,并且程序在之后能够使用它,它可以是作为一对元素本身,而不一定是迭代器。

8个回答

15

有两种选择:一是在原地使用然后删除它,二是将其移动到一个本地变量中,删除该条目,然后再使用它。

// use-remove
auto i = MyMap.find(wantedKey);
if (i != MyMap.end()) {
    // use-remove
    use(i->second);
    MyMap.erase(i);

    // or

    // move-remove-use
    auto x = std::move(i->second);
    MyMap.erase(i);
    use(x);
} else {
    // Not found
}

在C++11中,您可以使用auto x = std::move(i->second);进行移动、删除和使用。 - Casey
+1 @Casey。我为什么没想到呢?我已经相应修改了我的回答。 - Marcelo Cantos

4
我不知道有没有,但是你可以使用std::map::find来获取一个迭代器,然后在完成后将该迭代器作为参数调用std::map::erase

1
从您的变量命名来看,我认为您可能在这里混淆了概念。
itr = MyMap.pop(wantedKey);
//Do something with this element through 'itr'.

迭代器只指向容器中的元素。因此,如果您通过名为pop的函数(即使存在)获得了一个迭代器,则该迭代器将引用弹出的元素而不是您可能期望的之后或之前的元素,就像std::vector::erase一样。这是因为迭代器的目的是在容器中遍历元素。因此,如果一个元素不在容器中,您就无法获得指向它的迭代器。但是,即使您使用了erase函数返回的迭代器,它也不会引用您期望的元素
因此,您可以通过搜索元素、获取其迭代器并然后使用该迭代器调用erase来从映射中删除元素,正如许多人所指出的那样,但是您无法获得指向已删除元素的迭代器。希望这能澄清事情。

更新:如果您只想访问元素并使用它,则只需使用std::map::find获取迭代器,然后使用std::map::erase从映射中删除该项,一旦您完成使用迭代器。原因是即使您已经存储了迭代器的副本以供将来使用,一旦调用erase,它就会失效。要能够在删除后访问它,根据作用域,您可能需要复制它。

最后,你想要做的是一项非常常见的任务——根据关键字查找地图并对相关元素执行操作。很可能你有一个关键字列表需要遍历。你还应该查看函数对象, std::for_eachstd::transform。我意识到这不是在删除元素后对其进行操作,但考虑到它是相关操作,我想添加进来。例如:你可以将所有与关键字列表匹配的元素移动到另一个容器中(比如一个向量),然后使用上述方法对它们进行操作。


非常感谢您的解释。这是迄今为止最好的答案。但让我们尝试一下不同的方式:如果我能得到元素对并使用它,我会感到满意。 - Subway
谢谢您的详细说明。只是一个小注释,描述我的任务时您忘了提到我还想删除该元素。 - Subway
是的,你说得对。我没有这样做,因为我不想让事情变得太复杂。如果你有一组键和一个映射,那么你可以迭代键列表,对于每个键,在映射中找到相应的元素,进行操作,然后一步删除映射中的元素。但是,这需要了解BOOST库 - 特别是boost::lambda和boost::bind。理解BOOST的先决条件是理解C ++ STL库。不过你发现得很好 :) - Carl

0
itr = MyMap.find(wantedKey);
if(itr != MyMap.end()) {
  use( itr->second );
  MyMap.erase(itr);
}
your.uncle = bob;

0

你可能想要做的是

itr = MyMap.find('字符串中的内容');

来查找迭代器,然后使用它。

MyMap.erase(itr)

然后抹掉它。


0

0

使用 C++ 的 std::map<T, U>::find()

map.erase(map.find(key));

我没有使用c++11,但是很好奇:这种方式是否也可以启用using元素? - Subway
@Subway 你说的“using”是什么意思? - David G
我所说的“使用”,是指询问它的值等。 - Subway
你可以通过 m[key] 找到对应的值,这将返回与该键配对的值。这是你想要的吗? - David G
这正是我的意思,但我在问是否可以在同一操作中完成删除。 - Subway

0
我所做的方法如下。在我的情况下,地图存储std::shared_ptr值,使得复制相对便宜,并且对象所有权转移清晰明了。
auto it = MyMap.find( wantedkey );
if ( it == MyMap.end() ) throw runtime_error("not found");
auto ret = it->second;          // make copy of shared_ptr
MyMap.erase(it);
return ret;

调用者会得到一个具有至少一个引用计数的 shared_ptr(从副本中)。请注意,该函数必须通过值返回 shared_ptr 等。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接