C++从两个向量中删除重复元素

C++ remove duplicate elements from two vectors

本文关键字:删除 元素 向量 两个 C++      更新时间:2023-10-16

我有两个向量,std::vector<double> xvecstd::vector<double> yvec,每个向量都有数百万个相同大小的元素。但是xvec[i]和yvec[i]的组合用于定义唯一对象。例如

xvec = {1.0,2.0,2.0,3.0,2.0}
yvec = {5.0,1.0,1.5,2.0,1.0}

那么2.0_1.0组合就是重复元素,它应该从x和y向量中删除。

我希望在删除重复元素后返回xvec和yvec。按照示例,返回的xvec和yvec应该是

xvec = {1.0,2.0,2.0,3.0}
yvec = {5.0,1.0,1.5,2.0}

我知道如何使用排序和唯一函数对单个向量执行这样的任务。但有人能给我一些完成这个算法的想法吗?

我认为有三种可能性:

解决方案1

针对给定的问题,自己执行std::sortstd::uniquestd::unique很容易实现,但我现在不想实现排序算法。所以我不会给你举一个例子。

解决方案2

实现您自己的RandomAccessIteratorForwardIterator,并使用std::sortstd::unique

解决方案3

遍历这些值,并使用std::setstd::unordered_set检查当前值是否已经存在。

std::vector<double> xvec = {...};
std::vector<double> yvec = {...};
std::set<std::tuple<double,double> > set;
for (std::size_t i = 0; i < xvec.size();) {
    if (set.emplace(xvec[i], yvec[i]).second) {
        i++;
    } else {
        xvec.erase(xvec.begin() + i);
        yvec.erase(yvec.begin() + i);
    }
}

您可以将xvecyvec存储为成对的向量,即std::vector<std::pair<double,double> > vec。这将允许您轻松地使用std::sortstd::unique来实现您所描述的内容。我在下面包含了一些代码来演示这一点。

注意:下面的代码有点冗长,但将通过在重复数据消除之前和之后打印每个元素来演示一个有效的解决方案。代码应使用标志--std=c++11 进行编译

#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
    // Vector of pairs with duplicates.
    std::vector<std::pair<double,double> > vec = {{1,1},{1,3},{1,1},{2,4},{5,1}};
    std::cout << "Before:n";
    // Prints x - values
    std::cout << "x:";
    for (auto i : vec)
    {
        std::cout << i.first << "t";
    }
    std::cout << "ny:";
    // Prints y - values
    for (auto i : vec)
    {
        std::cout << i.second << "t";
    }
    std::cout << "nAfter:n";
    // The magic happens here :)
    std::sort(vec.begin(),vec.end());
    auto last = std::unique(vec.begin(), vec.end());
    vec.erase(last, vec.end());
    std::cout << "x:";
    // Prints x - values
    for (auto i : vec)
    {
        std::cout << i.first << "t";
    }
    std::cout << "ny:";
    // Prints y - values
    for (auto i : vec)
    {
        std::cout << i.second << "t";
    }
    return 0;
}