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

erasing duplicate element on even index in STL vector

本文关键字:元素 索引 STL 向量 删除      更新时间:2023-10-16

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

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

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

的例子:<>之前指数:0 1 2 3 4 5 6 7 8 9数据:a b b a和b b b b k^ ^ ^ ^ ^^ ^ ^ ^- ^ ^ -相同^ ^ ^^ ^ ^^——相同——^擦除后数据:a b b b h kconcatenatiom后数据:a b d b f h

没有相应的库函数。您要求做的事情甚至不类似于在示例中使用std::unique,因为这只会删除相邻的重复项。你得自己做这里的大部分工作。

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

但是,如果指定某个值为非法值,则不必跟踪索引,而是可以将元素更改为该非法值。然后可以使用std::remove

这不是一段特别优雅的代码,但只要默认的哈希和比较足够,它应该可以工作,并且应该是相当有效的:

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之后,vector变为:

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

对于一个非常类似的问题,你可以参考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
}