通过删除一些键和一些元素来更新地图的问题 [英] problem with updating a map by removing some keys and also some elements

查看:138
本文介绍了通过删除一些键和一些元素来更新地图的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一张地图。让我们说 map< int,vector< int> > 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:标签0
1:标签0
2:标签0
3:标签0
4:标签0
5 :标签1
6:标签0
7:标签1
8:标签0
9:标签1
10:标签0
11:标签1
12:标签0
13:标签0
14:标签1
15:标签1
16:标签1
17:标签1
18:标签0
19:标签0
20:标签0
21:标签1
22:标签0
23:标签0
24:标签0
25:标签1
26:标签1
27:标签0
28:标签0

当我停用else部分并运行上面的代码时,我得到了一个输出。但是,我想告诉你,这是一个错误的结果。我得到了应删除的额外密钥。我无法弄清楚为什么我得到了这个错误的结果。
如果我显示我所得到的钥匙清单,

  5 
7
9
11
14
15
16
17
20 - 错误
21
24 - 错误
25
26

您可以帮我纠正我的代码以获取我修改后的地图。提前谢谢。

解决方案

您的擦除逻辑错误,最终使用无效的迭代器。 (如果擦除迭代器然后继续使用该迭代器,那么你真的会从脚下拉出地毯。)



对于基于节点的容器(列表,地图) ,设置,无序),您通常擦除如下:

  for(auto it = c.begin(); it!= c.end();)
{
if(must_delete(* it))//或it-> first
{
c.erase(it ++); //先行前进,然后先删掉前一行
}
其他
{
++ it;
}
}

(这种模式是我最喜欢的后期理由修复增量运算符。)



对于连续的容器(vector,deque),一次删除一个元素是低效的,因为它会导致重复移动。这里首选的习惯是删除/删除,但如果您不想直接删除元素值,则需要提供合适的谓词。以下是lambdas的示例,为简洁起见:

  std :: vector< int> v; 
v.erase(std :: remove_if(v.begin(),v.end(),
[](int n) - > bool {return some_criterion(n);}),
v.end());

在您的情况下,您可以将lambda写为 [mylabel&]( n) - > bool {return mylabel [n] .Label()!= 1; } ;如果你没有lambdas,你可以写一个传统的谓词对象:

  struct LabelFinder 
{
LabelFinder (const LabelVector& lv):label(lv){}

inline bool operator()(int n)const
{
return label [n] .Label() != 1;
}

私人:
const LabelVector&标签;
};

现在使用:

  v.erase(std :: remove_if(v.begin(),v.end(),LabelFinder(mylabel)),v.end()); 


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.

解决方案

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:

for (auto it = c.begin(); it != c.end(); )
{
  if (must_delete(*it))  // or it->first
  {
    c.erase(it++); // advance first, then erase previous
  }
  else
  {
    ++it;
  }
}

(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:

std::vector<int> v;
v.erase(std::remove_if(v.begin(), v.end(),
                       [](int n)->bool{return some_criterion(n);}),
        v.end());

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:

struct LabelFinder
{
  LabelFinder(const LabelVector & lv) : label(lv) { }

  inline bool operator()(int n) const
  {
    return label[n].Label() != 1;
  }

private:
  const LabelVector & label;
};

Now use:

v.erase(std::remove_if(v.begin(), v.end(), LabelFinder(mylabel)), v.end());

这篇关于通过删除一些键和一些元素来更新地图的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆