如何擦除向量中的最后一个和/或唯一元素?

时间:2011-11-24 20:03:44

标签: c++

我需要根据它们的值从矢量中删除元素,我已经尝试了成语erase-remove_if但是要擦除项目的条件并不那么简单,我尝试了类似

的内容
map<string, TLorentzVector> map_jets
vector<pair<string,double> > jets_pt


  for( vector<pair<string,double> >::iterator it1 = jets_pt.begin(); it1 != jets_pt.end(); ){
   if( fabs(map_jets[it1->first].PseudoRapidity()) > 2.5 )
      jets_pt.erase(it1);

但是当segmentation violation的尺寸= 1时我得到jets_pt。 整个程序获取实验数据并循环,地图跟踪事件的名称和我需要的相关变量,而向量存储地图的字符串和我需要跟踪的值。 我想从向量中删除那些满足一些条件的值

  if( fabs(map_jets[it1->first].PseudoRapidity()) > 2.5 )
      jets_pt.erase(it1);

    if( map_jets[it->first].DeltaR(map_leps["lep1"]) < 0.4 && map_jets[it->first].DeltaR(map_leps["lep2"]) < 0.4 && map_jets[it->first].DeltaR(map_leps["lep3"]) )                                            
        jets_pt.erase(it);  

     if( jets_emfr[k] > 0.9 )                                                                                                                                                                                  
        jets_pt.erase(it);  

4 个答案:

答案 0 :(得分:2)

这听起来像std::remove_if算法的工作,可用于从容器中删除与给定谓词匹配的元素。

这样的事情应该有效:

bool myPredicate( pair<string, double> element ) {
  return fabs(map_jets[elem.first].PseudoRapidity()) > 2.5
         || (map_jets[elem.first].DeltaR(map_leps["lep1"]) < 0.4 && ... )    
         || ...
}

jets_pt.erase( remove_if( jets_pt.begin(), jets_pt.end(), myPredicate ),
               jets_pt.end() );

答案 1 :(得分:1)

我假设您在实际代码中实际上为循环中的某个地方的迭代器调用operator++。但是,您仍然遇到擦除使迭代器无效的问题,因此您需要执行

it = jets_pt.erase(it1);

然而,remove_if - erase在这里确实是一个更合适的解决方案 我应该重新推荐以下内容:

struct remove_functor
{
    map<string, TLorentzVector>& map_jets;
    map<...>& map_leps;

    remove_functor(map<string, TLorentzVector>& m_jets, map<...>& m_leps): map_jets(m_jets), map_leps(m_leps)
    {}

    bool operator()(const pair<string,double>& p)
    {
        return (fabs(map_jets[p.first].PseudoRapidity()) > 2.5) 
           ||  ((map_jets[p.first].DeltaR(map_leps["lep1"]) < 0.4)
             && (map_jets[p.first].DeltaR(map_leps["lep2"]) < 0.4)
             && (map_jets[p.first].DeltaR(map_leps["lep3"]));
    }
 }

然后你可以简单地使用

jets_pt.erase(remove_if(jets_pt.begin(), jets_pt.end(), remove_functor(map_jets, map_leps)), jets_pt.end());

当然在c ++ 0x中你可以简单地使用lambda函数:

auto predicate = [&](const pair<string, double>& p) {bool operator()(const pair<string,double>& p)
    {
        return (fabs(map_jets[p.first].PseudoRapidity()) > 2.5) 
           ||  ((map_jets[p.first].DeltaR(map_leps["lep1"]) < 0.4)
             && (map_jets[p.first].DeltaR(map_leps["lep2"]) < 0.4)
             && (map_jets[p.first].DeltaR(map_leps["lep3"]));
    };
jets_pt.erase(remove_if(jets_pt.begin(), jets_pt.end(), predicate), jets_pt.end());

predicate = [&](...){...};创建一个仿函数(通过lambda语法),它通过引用捕获所有使用的变量(map_jets, map_leps,...,由[&]表示),可用于{ {1}}。 remove_if表示编译器应该推断变量的类型(因为我们没有编译器为这个lambda生成的类型的名称)。

答案 2 :(得分:1)

尝试以下操作(近似c ++ 11,我无权访问此计算机上符合c ++ 11的编译器):

jets_pt.erase(
  remove_if(
    jets_pt.begin(),
    jets_pt.end(),
    [&](const pair<string,double> &p) {
      return fabs(map_jets[p.first].PseudoRapidity()) > 2.5;
    }),
  jets_pt.end());

基本上,你想从remove_if返回的迭代器中删除直到向量的末尾。您可以根据需要将谓词编辑为remove_if。

答案 3 :(得分:0)

迭代时不要删除条目!您使循环约束无效。