2012-04-13 83 views
2

时,我有一个std ::地图,是有一种优雅的方式在同一时间:如何更改地图中的元素并获取其位置?

  1. 插入/编辑元素赋予其关键
  2. 得到一个迭代器插入的元素

我发现最好的方法是防止在地图上做2查找是:

std::map<int, int> myMap; 
//do some stuff with the map 
std::map<int,int>::iterator it = myMap.insert(std::pair<int, int>(0,0)).first; 
it->second = 0; //necessary because insert does not overwrite the values 

是否有可能做到这两点在一条语句/行? 感谢

+1

请注意,地图的价值类型不'对' ,而是'pair '。 – 2012-04-13 20:19:07

+0

插入或编辑,你想要哪一个?很明显,你已经有了一个插入的单线程,那么问题到底是什么? – 2012-04-13 20:20:17

+0

我相信你找到了最有效的方法。如果你只是不喜欢它的外观,实现一个“替换”功能,结合这两个步骤,但即使这样做将按照你的例子来实现。 – Chad 2012-04-13 20:20:40

回答

4

唉,STL函数和容器并不总能达到您所期望的。这里有两个通用版本,第一个更喜欢你上面的代码:

template<class Map> 
inline typename Map::iterator ForceInsert1( 
    Map&       m, 
    const typename Map::key_type& k, 
    const typename Map::data_type& d) 
{ 
    typename Map::iterator it = m.insert( 
     typename Map::value_type(k, d)).first; 
    it->second = d; // only necessary if the key already exists 
    return it; 
} 

template<class Map> 
inline typename Map::iterator ForceInsert2( 
    Map&       m, 
    const typename Map::key_type& k, 
    const typename Map::data_type& d) 
{ 
    typename Map::iterator it = m.find(k); 
    if(it != m.end()) 
    { 
     it->second = d; 
    } 
    else 
    { 
     it = m.insert(typename Map::value_type(k, d)).first; 
    } 
    return it; 
} 

typedef std::map<int, int> MyMap; 
void Foo(MyMap& myMap) 
{ 
    ForceInsert1(myMap, 42, 100); 
    ForceInsert2(myMap, 64, 128); 
} 
+0

typename Map :: data_type()是做什么的?那是默认的构造函数? – lezebulon 2012-04-13 20:43:21

+0

它是(或者 - 我改变了它)。如果使用[]运算符,data_type只需要默认构造。作为新的注释说明,只有在密钥已经存在的情况下才需要分配。否则,insert事实上会设置与插入的键相关的数据。 – metal 2012-04-13 20:52:38

+0

更好的办法是在ForceInsert2中使用std :: lower_bound,然后将其作为提示插入。有关更多信息,请参阅Scott Meyers的“Effective STL”。 – metal 2013-02-04 18:23:55

0
myMap[0] = 0; 

这条线将插入为0的键的值,如果它不存在它,并且在任一情况下,将该密钥的值设置为0

这大致类似于你有什么,可制作成一条线:

myMap.insert(std::make_pair(0,0)).first->second = 0; 
+0

是的,但我也想返回一个迭代器到插入的元素 – lezebulon 2012-04-13 20:21:36

1

你可以这样做:

map<int, int> m; 
map<int, int>::iterator iter; 
(iter = (m.insert(make_pair(1,1))).first)->second = 5; 

显然make_pair中的第二个值是无关紧要的(只要它是正确的类型)。在这里,您设置的值的迭代器指向到5

是有点厚脸皮,在技术上这也将是一个声明:

iter = myMap.insert(make_pair(0,0)).first, iter->second = 0; 

逗号(,)运营商保证所有的副作用发生在评估rhs之前,所以iter具有正确的值

+0

好吧,这将工作。但我仍然觉得很烦,你需要制作第二种类型的无用副本(“1”)才能工作。显然,这对整数并不重要,但更大的结构呢? – lezebulon 2012-04-13 20:39:05

+2

当结构足够大以至于不止一次复制是一个问题时,您可能会首先发现密钥并在必要时插入(如果需要,可以创建一个模板函数来执行此操作多次的逻辑)。事实上,你正在为'pair'制作一个副本,然后在插入副本时再插入副本(无论如何你都需要)。所以建议的版本最多可以生成树副本,而至少需要两个树副本。 – Attila 2012-04-13 20:47:34

1

如果你只是想要的值,而不是对:

int& value = myMap[0] = 0;