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

How to erase last and/or unique element in a vector?

本文关键字:最后 元素 唯一 何擦除 擦除      更新时间:2023-10-16

我需要根据它们的值从向量中擦除元素,我尝试了习语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);

但是当jets_pt的大小为1时,我得到一个segmentation violation。整个程序获取实验的数据并循环,map记录事件的名称和我需要的相关变量,而vector存储map的字符串和我需要记录的值。我想从向量中删除那些不满足几个条件的值

  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);  

这听起来像是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() );

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

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,...,由[&]表示),这些变量可用于remove_ifauto意味着编译器应该推断变量的类型(因为我们没有编译器为这个lambda生成的类型的名称)。

尝试以下操作(近似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返回的迭代器中擦除vector对象的末尾。您可以根据需要编辑谓词remove_if。

在迭代时不要擦除条目!