我有一张地图。可以说 map; > mymap1
。
我想通过删除一些“键”并从所选键的向量部分中删除不需要的“元素”来更新 mymap1。要删除的“键”或“元素”由另一个向量给出,称为“mylabel”。实际上,我需要保留在映射中的是标签等于 1 的值。(最后,键必须仅包含标签为 1 的元素。)
我已经实现了这个(参见下面的代码),但得到了一些编译器错误。
map<int, vector<int> > mymap1;
map<int, vector<int> >::iterator map1;
for (map1=mymap1.begin();map1!=mymap1.end();map1++){
int key = map1->first;
if (mylabel[key].Label() != 1){ mymap1.erase(key);
}
else{
vector<int> &myvec = map1->second;
for (vector<int>::iterator rn=myvec.begin(); rn!=myvec.end(); rn++){
if (mylabel[*rn].Label() != 1) myvec.erase(myvec.begin()+(*rn));
}
}
}
为了让您有一个想法,我展示了我的地图的一些示例。
0 1 2 6 10
1 0 2 4 3 6
2 0 1 3 5 8
3 1 2 4 5 7
4 1 3 6 7
5 2 3 8 7 9
6 1 0 7 4
7 6 4 3 5 9 11 10 13 12
8 2 5 9 11 18 15 19 20 22
9 5 7 11 8
10 0 7 14 16
11 9 7 8 13
12 7 13 14
13 7 12 11 14 15
14 12 10 16 13 15 17
15 13 14 8 17 19
16 14 10 17 21
17 14 16 15 21 18
18 8 20 19 17 26 27
19 8 15 18
20 8 18
21 16 17 23 24
22 8
23 25 21 24 26
24 23 21
25 23 26
26 23 25 18
27 18 28
28 27
如果我给你看我的 mylabel,它如下。
for(int c=0;c<mylabel.size();c++){
cout<<c<<" : "<<"label "<<mylabel[c].Label()<<endl;
}
0 : label 0
1 : label 0
2 : label 0
3 : label 0
4 : label 0
5 : label 1
6 : label 0
7 : label 1
8 : label 0
9 : label 1
10 : label 0
11 : label 1
12 : label 0
13 : label 0
14 : label 1
15 : label 1
16 : label 1
17 : label 1
18 : label 0
19 : label 0
20 : label 0
21 : label 1
22 : label 0
23 : label 0
24 : label 0
25 : label 1
26 : label 1
27 : label 0
28 : label 0
当我停用 else 部分并运行上面的代码时,我得到了一个输出。但是,我想告诉你,这是一个错误的结果。我收到了应该删除的额外密钥。我不明白为什么会得到这个错误结果。
如果我显示我得到的钥匙列表,
5
7
9
11
14
15
16
17
20 - wrong
21
24 - wrong
25
26
您能帮我纠正我的代码以获得修改后的地图吗?提前致谢。
I have a map. lets say map<int, vector<int> > mymap1
.
I want to update mymap1 by deleting some “keys” and also removing unwanted “elements” from the vector part of the selected keys. The “key’ or the “element” going to be deleted is given from another vector, known as “mylabel”. Actually, What I need to remain in my map is the values whose label is equal to 1. (At the end, keys must have the elements whose label are 1 only.)
I have implemented this (see code below), but got some compiler errors.
map<int, vector<int> > mymap1;
map<int, vector<int> >::iterator map1;
for (map1=mymap1.begin();map1!=mymap1.end();map1++){
int key = map1->first;
if (mylabel[key].Label() != 1){ mymap1.erase(key);
}
else{
vector<int> &myvec = map1->second;
for (vector<int>::iterator rn=myvec.begin(); rn!=myvec.end(); rn++){
if (mylabel[*rn].Label() != 1) myvec.erase(myvec.begin()+(*rn));
}
}
}
for you to get an idea, i am showing some example of my map.
0 1 2 6 10
1 0 2 4 3 6
2 0 1 3 5 8
3 1 2 4 5 7
4 1 3 6 7
5 2 3 8 7 9
6 1 0 7 4
7 6 4 3 5 9 11 10 13 12
8 2 5 9 11 18 15 19 20 22
9 5 7 11 8
10 0 7 14 16
11 9 7 8 13
12 7 13 14
13 7 12 11 14 15
14 12 10 16 13 15 17
15 13 14 8 17 19
16 14 10 17 21
17 14 16 15 21 18
18 8 20 19 17 26 27
19 8 15 18
20 8 18
21 16 17 23 24
22 8
23 25 21 24 26
24 23 21
25 23 26
26 23 25 18
27 18 28
28 27
if i show you my mylabel, it is as follows.
for(int c=0;c<mylabel.size();c++){
cout<<c<<" : "<<"label "<<mylabel[c].Label()<<endl;
}
0 : label 0
1 : label 0
2 : label 0
3 : label 0
4 : label 0
5 : label 1
6 : label 0
7 : label 1
8 : label 0
9 : label 1
10 : label 0
11 : label 1
12 : label 0
13 : label 0
14 : label 1
15 : label 1
16 : label 1
17 : label 1
18 : label 0
19 : label 0
20 : label 0
21 : label 1
22 : label 0
23 : label 0
24 : label 0
25 : label 1
26 : label 1
27 : label 0
28 : label 0
When I am deactivating the else part and running above code I got an output. But, I want to say you that it is a wrong result. I am getting extra keys that should be deleted. I can’t figure out why I got this fault result.
if i show the list of keys what i got,
5
7
9
11
14
15
16
17
20 - wrong
21
24 - wrong
25
26
could you please help me to rectify my code in order to get my modified map. thanks in advance.
发布评论
评论(2)
您的擦除逻辑是错误的,最终会使用无效的迭代器。 (如果你删除一个迭代器,然后继续使用该迭代器,那么你实际上是在自取灭亡。)
对于基于节点的容器(列表、映射、集合、无序),通常按如下方式删除:(
这种模式这是我最喜欢的后修复增量运算符的理由。)
对于连续容器(向量、双端队列),一次擦除一个元素效率很低,因为它会导致重复移动。这里的首选习惯用法是“删除/擦除”,但如果您不想直接按元素值删除,则需要提供合适的谓词。为了简洁起见,下面是 lambda 的示例:
在您的情况下,您可以将 lambda 编写为
[mylabel&](n)->bool{ return mylabel[n].Label() != 1; }
;或者如果没有 lambda,则编写传统的谓词对象:现在使用:
Your erasing logic is wrong, and you end up using invalid iterators. (You're literally pulling the rug out from under your feet if you erase an iterator and then keep using that iterator.)
For node-based containers (list, map, set, unordered), you typically erase as follows:
(This patterns is my favourite justification for the post-fix increment operator.)
For contiguous containers (vector, deque), erasing one element at a time is inefficient, because it incurs repeated moves. The preferred idiom here is "remove/erase", but it requires that you supply a suitable predicate if you don't just want to remove straight by element value. Here's an example with lambdas, for brevity:
In your situation, you could write the lambda as
[mylabel&](n)->bool{ return mylabel[n].Label() != 1; }
; or write a traditional predicate object if you don't have lambdas:Now use:
问题出在
for
循环中。std::vector::erase()
将迭代器返回到新位置,后跟删除的项目。因此循环应写为:阅读文档:
顺便说一句,我对此表示怀疑:
你确定要第一个吗?
删除不等于 1 的元素的惯用方法是:
它称为:
The problem is in the
for
loop.std::vector<T>::erase()
returns iterator to the new position followed by the erased item. So the loop should be written as:Read the doc:
By the way, I doubt on this:
Are you sure you want the first one?
An idiomatic way to erase elements which are not equal to one is this:
It's called :