在STL向量中擦除偶数索引上的重复元素

时间:2011-11-13 18:08:26

标签: c++ stl

我知道如何擦除矢量上的重复元素。

data.erase(std::unique(data.begin(), data.end()), data.end());

如何删除索引0,2,4,6,8 ......上的重复元素?

示例:

 index : 0 1 2 3 4 5 6 7 8 9
 data  : a b a d b f a h b k
         ^   ^   ^   ^   ^
         ^   ^   ^   ^
                 ^--same-^
         ^   ^       ^
         ^   ^       ^ 
         ^-----same--^  
after erasing
data  :  a b   d b f   h   k

after concatenatiom
data :   a b d b f h

3 个答案:

答案 0 :(得分:2)

这没有库函数。您要求做的事情甚至不像您在示例中那样使用std::unique,因为这只会删除相邻的重复项。你必须自己完成大部分工作。

创建一个集合。循环遍历向量,跳过奇数索引。在循环时,检查该元素是否在集合中。如果是,则标记要删除的索引,否则,将该元素添加到集合中。从向量中删除所有标记的索引。您不能使用std::removestd::remove_if,因为它们适用于元素值,而不是索引。你必须使用普通的旧循环。

虽然,如果您将某个值指定为非法,那么您实际上可以将元素更改为该非法值,而不是跟踪索引。然后你可以使用std::remove

答案 1 :(得分:2)

这不是一个特别优雅的代码,但只要默认哈希并且比较足够,它应该有效,并且应该合理有效:

template <typename T>
void RemoveEvenDuplicates(std::vector<T>& v) {

    std::unordered_set<T> s;
    std::vector<T>::size_type i = 0;

    auto last = std::remove_if(
        v.begin(),
        v.end(),
        [&s, &i] (const T& element) -> bool {
            if (i++ % 2 == 0) {
                auto pair = s.insert(element);
                return !pair.second;
            }
            return false;
        }
    );

    v.erase(last, v.end());

}

void main() {

    std::vector<std::string> v;
    v.push_back("a");
    v.push_back("b");
    v.push_back("a");
    v.push_back("d");
    v.push_back("b");
    v.push_back("f");
    v.push_back("a");
    v.push_back("h");
    v.push_back("b");
    v.push_back("k");

    RemoveEvenDuplicates(v);

}

调用RemoveEvenDuplicates后,矢量变为:

[7]("a","b","d","b","f","h","k")

答案 2 :(得分:0)

您可以将this非常好的帖子Fred Nurk中提出的建议(一个)提交给一个非常相似的问题。 您需要额外的++x;才能触及偶数(或奇数)索引元素。

示例:

set<string> found;
for (list<string>::iterator x = the_list.begin(); x != the_list.end();) {
  if (!found.insert(*x).second) {
    x = the_list.erase(x);
  }
  else {
    ++x;
  }
  ++x; // <-- one increment added to skip the odd-indexed elements
}