C++ 从std::vector中删除复制结构成员

C++ 从std::vector中删除复制结构成员,c++,boost,vector,struct,C++,Boost,Vector,Struct,我有一个结构成员向量,如下所示: struct pnt { bool has; int num; }; std::vector<pnt> myvector; 我想做的是找到重复的成员(就具有相同的int num而言),并删除具有false bool member的成员。 所以我的向量变成这样: myvector (num): 3 4 3 5 7 8 9 10

我有一个结构成员向量,如下所示:

struct pnt
{
    bool has;
    int num;
};
std::vector<pnt> myvector;
我想做的是找到重复的成员(就具有相同的int num而言),并删除具有false bool member的成员。 所以我的向量变成这样:

myvector (num): 3 4 3 5 7 8 9 10                                                         
myvector (has): 1 1 1 1 0 0 0 1 
为此,我编写了以下函数:

void removeDuplicatedPnt(pnt_vec& myvector)
{
  std::vector<pnt>::iterator pnt_iter;
  for( pnt_iter = myvector.begin(); pnt_iter != myvector.end(); ++pnt_iter)
  {
      if(pnt_iter->has)
      {
          if(pnt_iter->num == (pnt_iter+1)->num)
          {
              myvector.erase(pnt_iter+1);
          }
          if(pnt_iter == myvector.begin())
          {
             continue;
          }
          if(pnt_iter->num == (pnt_iter-1)->num)
          {
              myvector.erase(pnt_iter-1);
              pnt_iter++;
          } 
       }
    }
}
void removedupplicatedpnt(pnt_vec&myvector)
{
std::vector::迭代器pnt_iter;
对于(pnt_iter=myvector.begin();pnt_iter!=myvector.end();++pnt_iter)
{
如果(pnt_iter->has)
{
如果(pnt_iter->num==(pnt_iter+1)->num)
{
myvector.erase(pnt_iter+1);
}
如果(pnt_iter==myvector.begin())
{
继续;
}
如果(pnt_iter->num==(pnt_iter-1)->num)
{
myvector.erase(pnt_iter-1);
pnt_iter++;
} 
}
}
}
我也可以通过顺序检查成员来完成。但真正的向量可能很长。所以,这就是为什么我首先查找具有true boolean的成员,然后检查下一个和上一个成员。问题是我如何在效率和健壮性方面修改上述代码


注意:我只能使用C++03(不是C++11)。我也可以使用boos(1.53版),所以如果认为那里有任何有用的功能,请随意使用。:)

您可以将std::sort和std::unique与自定义比较谓词一起使用:

[](const pnt& a, const pnt& b) { return a.num < b.num; }

但这只是切向相关的

您可以使用此算法:

  • 收集所有
    num
    s,其中
    has
    true
    集合中
  • 再次检查
    向量
    ,删除
    集合中存在的
    has
    false
    num
    的所有条目
下面是一个示例实现:

struct filter {
    set<int> seen;
    bool operator()(const pnt& p) {
        return !p.has && (seen.find(p.num) != seen.end());
    }
};
...
filter f;
for (vector<pnt>::const_iterator i = v.begin() ; i != v.end() ; i++) {
    if (i->has) {
        f.seen.insert(i->num);
    }
}
v.erase(remove_if(v.begin(), v.end(), f), v.end());
struct过滤器{
集看到;
布尔运算符()(常量pnt&p){
return!p.has&(seen.find(p.num)!=seen.end());
}
};
...
滤波器f;
for(vector::const_迭代器i=v.begin();i!=v.end();i++){
如果(i->has){
f、 seen.insert(i->num);
}
}
v、 擦除(如果(v.begin(),v.end(),f),v.end(),则删除_);

if(pnt\u iter->num==(pnt\u iter-1)->num)
如果
pnt\u iter
是向量中的第一项,则此操作将失败。@dasblinkenlight抱歉,我编辑了question@PaulMcKenzie谢谢你的通知,我编辑了这个问题。请注意,使用迭代器可能不是最好的选择,因为它们可能都是。在这种特殊情况下,使用显式索引可能是一个更好的选择。@dasblinkenlight我将我的答案固定为c++03。请注意,您也在对他的向量进行排序。在一组:)(我知道这是不同的,但它不是很大)通过“排序”,我的意思是改变向量本身中项目的顺序。我只对
num
部分使用
set
,并将其与向量本身分开存储。我希望我可以使用无序集和lambda,但这都是C++11:-(@dasblinkenlight我打赌使用
无序集只会(a)增加噪声并支持代码(
std::hash
)(b)让它慢一点。对于OP中的情况,我不认为任何东西都会比向量快,即使你需要在副本上排序。但我很乐意承认我太懒了,无法证明:)@dasblinkenlight/OP找到时间添加C++03版本@H'H,我知道。如果这不是故意的,也没关系。还有一个答案说明了如何做到这一点。使用混合方法可能会获得更好的性能,但我认为这并不重要。如果确实如此,我认为您需要重新考虑数据结构:)
#include <boost/range.hpp>
#include <boost/range/algorithm.hpp>
#include <iostream>

using namespace boost;

struct pnt {
    int num;
    bool has;

    pnt(int num = 0, bool has = false) : num(num), has(has) {}

    friend bool operator<(pnt const& a, pnt const& b) { return a.num<b.num; }
    friend bool operator==(pnt const& a, pnt const& b) { return a.num==b.num; }
};

int main() {
    std::vector<pnt> v { {10,0 },{10,1 },{9,0 },{8,0 },{7,0 },{5,1 },{5,0 },{3,1 },{4,0 },{4,1 },{3,1 } };

    for (pnt p : boost::unique(boost::sort(v)))
        std::cout << "{ num:" << p.num << ", has:" << p.has << "}\n";
}
it = std::find(v.begin(), v.end(), 3); // find a `pnt` with `num==3`
struct filter {
    set<int> seen;
    bool operator()(const pnt& p) {
        return !p.has && (seen.find(p.num) != seen.end());
    }
};
...
filter f;
for (vector<pnt>::const_iterator i = v.begin() ; i != v.end() ; i++) {
    if (i->has) {
        f.seen.insert(i->num);
    }
}
v.erase(remove_if(v.begin(), v.end(), f), v.end());