C++映射擦除(开始,结束)不起作用
C++ map erase(begin, end) not working
我正试图通过使用C++API for map来简化我的生活。通过map.erase(begin, end)
方法,我希望删除[begin, end)
之间的所有条目。所以我的方法实现了CCD_ 3的定义如下。
79 void
80 ObjectFinder::flush(uint64_t tableId) {
81
82 RAMCLOUD_TEST_LOG("flushing object map");
83 std::map<TabletKey, ProtoBuf::Tablets::Tablet>::iterator lower;
84 std::map<TabletKey, ProtoBuf::Tablets::Tablet>::iterator upper;
85 std::map<TabletKey, ProtoBuf::Tablets::Tablet>::iterator it;
86 KeyHash keyHash = Key::getHash(tableId, "", 0);
87 TabletKey key(tableId, keyHash);
88
89 std::cout << "before the loop" << std::endl;
90 for (it = tableMap.begin(); it != tableMap.end(); it++) {
91 std::cout << it->first.first << std::endl;
92 }
93 lower = tableMap.lower_bound(key);
94 upper = tableMap.upper_bound(key);
95
108 tableMap.erase(lower, upper);
109 std::cout << "After the erase" << std::endl;
110 for (it = tableMap.begin(); it != tableMap.end(); it++) {
111 std::cout << it->first.first << std::endl;
112 }
}
但是,id
值没有被删除:
id = 99
before the loop
1
99
After the erase
1
99
我编写了自己的comparison
函数,以重载默认方法:
35 typedef std::pair<uint64_t, KeyHash> TabletKey;
36
37 /*
38 * The object CmpTabletKey is used to override the default comparison
39 * definition from the C++ Map.
40 */
41 struct CmpTabletKey {
42 bool operator()(const TabletKey& key1, const TabletKey& key2) const {
43 return ((key1.first < key2.first) ||
44 (key1.first == key2.first && key1.second < key2.second));
}
}
有人能告诉我为什么erase
没有按预期工作吗?我是否也必须将CmpTabletKey
的定义赋予iterator
?更新这是我以前的实现:它工作得很好,可以做我想做的事:然而,这是一个O(n)方法,我想要一个更快的实现:
117 std::map<TabletKey, ProtoBuf::Tablets::Tablet>::iterator it;
118 for (it = tableMap.begin(); it != tableMap.end(); ) {
119 if (tableId == it->first.first) {
120 tableMap.erase((it++)->first);
121 } else {
122 ++it;
123 }
124 }
从迭代器的定义来看,您似乎没有使用自定义比较器创建映射。
我认为地图应该创建为:
std::map<TabletKey, ProtoBuf::Tablets::Tablet, CmpTabletKey > tableMap; //CmpTabletKey is passed as the comparator type
And your iterators become:
std::map<TabletKey, ProtoBuf::Tablets::Tablet, CmpTabletKey>::iterator lower;
std::map<TabletKey, ProtoBuf::Tablets::Tablet, CmpTabletKey>::iterator upper;
std::map<TabletKey, ProtoBuf::Tablets::Tablet, CmpTabletKey>::iterator it;
如果未指定CmpTabletKey
作为类型,则映射将使用默认比较器。
映射容器最多包含每个键的一个副本,我认为您想要做的是擦除TableID相同的所有元素,但您已经使用一对对元素进行了排序,因此您必须迭代所有映射并选择符合谓词的元素。
如果可以的话,应该使用std::multimap并创建一个只涉及TableID的比较器。
编辑:
好吧,所以你想删除所有具有特定ID的元素。但实际上,你的地图正在寻找的是一个具有特定tableID和特定keyHash的元素。
您有几种解决方案,其中一种是O(n)(您现有的解决方案),另一种选择是使用另一种满足您需求的数据结构。我认为您应该使用多映射或未定义的多映射(hast_table)。
这里有一个简化的示例,可以帮助您实现目标。
让我们用一对钥匙做一张地图:
#include <map>
#include <utility>
typedef std::pair<int, int> key_type;
std::map<key_type, void *> mymap = { { { 1, 2}, NULL }
, { { 5, 0}, NULL }
, { { 5, 7}, NULL }
, { { 6, 3}, &mymap } };
现在假设我们想要从mymap
中移除其第一个关键部分等于5
的所有元素。这里有一个解决方案:
for (auto it = mymap.begin(); it != mymap.end(); )
{
if (it->first.first == 5) { mymap.erase(it++); }
else { ++it; }
}
取2…由于您的原始文件甚至没有考虑key.second
值,我猜问题出在CmpTabletKey
中,但这次原因不同。与原始实现功能等效的比较运算符是:
35 typedef std::pair<uint64_t, KeyHash> TabletKey;
36
37 /*
38 * The object CmpTabletKey is used to override the default comparison
39 * definition from the C++ Map.
40 */
41 struct CmpTabletKey {
42 bool operator()(const TabletKey& key1, const TabletKey& key2) const {
43 return (key1.first < key2.first);
}
}
我怀疑,由于您当前的实现也考虑了.second
值,因此功能与原来的有所不同。擦除同一个对象的下界和上界之间的所有内容本质上会擦除与该对象等价的所有键,但是您有KeyHash keyHash = Key::getHash(tableId, "", 0);
和TabletKey key(tableId, keyHash);
,但key
的键值并没有具体在您的映射中。您的比较运算符也是特定于的,因此它不会仅评估.first
值的等价性。
同时,比较有必要如此严格,因为我相信地图搜索基本上是说"如果A!<B和B!<A,那么A==B"。这意味着您将无法正确插入值,因为等价性也不关心.second
。由于这些相互冲突的定义,我认为您当前的实现不会起作用。
编辑:Derp。试试这个:
79 void
80 ObjectFinder::flush(uint64_t tableId) {
81
82 RAMCLOUD_TEST_LOG("flushing object map");
83 std::map<TabletKey, ProtoBuf::Tablets::Tablet>::iterator lower;
84 std::map<TabletKey, ProtoBuf::Tablets::Tablet>::iterator upper;
85 std::map<TabletKey, ProtoBuf::Tablets::Tablet>::iterator it;
86 //KeyHash keyHash = Key::getHash(tableId, "", 0);
TabletKey keylower(tableId, KeyHash::MINIMUM);
TabletKey keyupper(tableId, KeyHash::MAXIMUM);
87 //TabletKey key(tableId, keyHash);
88
89 std::cout << "before the loop" << std::endl;
90 for (it = tableMap.begin(); it != tableMap.end(); it++) {
91 std::cout << it->first.first << std::endl;
92 }
93 lower = tableMap.lower_bound(keylower);
94 upper = tableMap.upper_bound(keyupper);
95
108 tableMap.erase(lower, upper);
109 std::cout << "After the erase" << std::endl;
110 for (it = tableMap.begin(); it != tableMap.end(); it++) {
111 std::cout << it->first.first << std::endl;
112 }
}
其中,KeyHash::MINIMUM
是最低密钥哈希值的静态常量,KeyHash::MAXIMUM
是最大值。请使用当前的比较结构。
- 我的神经网络不起作用 [XOR 问题]
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- C++为什么尽管我调用了void函数,它却不起作用
- 为什么在保护模式下继承升级不起作用
- 循环在计数器中不起作用
- 在其他文件中创建类时在 c++ 项目中不起作用
- Visual studio代码重构似乎不起作用(例如,重命名符号-f2)
- 为什么二进制搜索在我的测试中不起作用
- 我的代码中有错误吗?使用BGI图形的C++代码对我不起作用
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 带有指定长度字符* 参数的 std::regex_search 在 VS2017 中不起作用?
- Bjarne Stroustrup Book - std_lib_facilities.h - 不起作用(未知类型名称)
- 为什么简单的算术减法在"if"条件下不起作用?
- 获取热线(CIN,答案5);在我的程序结束时不起作用
- 文件结束输入不起作用
- C++ 开始和结束不起作用
- Qt QJsonModel 在网络请求结束时不起作用
- C++映射擦除(开始,结束)不起作用
- 文件结束检查不起作用 (C++)