简体   繁体   English

从C ++中另一个向量中包含的另一个向量中删除所有元素?

[英]Removing all elements from one vector that are contained in the other in C++?

I have 2 vectors vc and v2 I want to remove all elements from vc that are contained in v2. 我有2个向量vcv2我想删除v2.中包含的vc中的所有元素v2. I try to do this by 2 nested loops. 我尝试通过2个嵌套循环来做到这一点。 However the compiler gives an error: Debug Assertion Failed . 但是编译器发出错误: Debug Assertion Failed I would like to ask why is that and how can I fix it? 我想问为什么,我该如何解决? Thanks in advance! 提前致谢!

#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector <string> vc;
vector <string> v2;
int main()
{
    vc.push_back("ala");
    vc.push_back("bala");
    vc.push_back("test");
    vc.push_back("sample");
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    v2.push_back("test");
    v2.push_back("bala");
    for (auto i = vc.begin(); i != vc.end(); i++) {
        for (auto j = v2.begin(); j != v2.end(); j++) {
            if (i == j) {
                vc.erase(i);
            }
        }
    }
    //it should print only ala and sample after  the removal process, but it gives
    //debug assertion error
    for (int i = 0; i < vc.size(); i++) {
        cout << vc[i] << endl;
    }
}

As pointed out in the comments, you have undefined behavior in your snippet twice. 正如评论中指出的那样,您的代码段中有两次未定义的行为。 First, you compare two iterators that don't refer to the same container. 首先,比较两个不引用同一容器的迭代器。 Second, the vc iterator and loop variable i is invalidated when vc.erase(i) is called. 其次,当vc.erase(i)时, vc迭代器和循环变量i无效。

Fixing this is a good example for leveraging the <algorithm> header and common idioms, as implementing such things by hand is error prone. 修复此问题是利用<algorithm>标头和常用习惯用法的一个很好的例子,因为手动实现这些事情很容易出错。 What you need is the so called erase-remove-idiom : 你需要的是所谓的擦除 - 删除 - 成语

#include <algorithm>

auto isInV2 = [&v2](const auto& element){
    return std::find(v2.cbegin(), v2.cend(), element) != v2.cend(); };

vc.erase(std::remove_if(vc.begin(), vc.end(), isInV2), vc.end());

Depending on the circumstances of your application, it might also be suitable to keep the vectors sorted (or sort them at some point) and then use binary search to check if an element is present, which scales better with larger sequences. 根据应用程序的具体情况,也可能适合保持向量排序(或在某个点对它们进行排序),然后使用二进制搜索来检查元素是否存在,哪个元素可以更好地扩展。

auto isInV2LogN = [&v2](const auto& element){
    return std::binary_search(v2.cbegin(), v2.cend(), element); };

// Important: v2 must be sorted, otherwise std::binary_search doesn't work:
std::sort(v2.begin(), v2.end());

vc.erase(std::remove_if(vc.begin(), vc.end(), isInV2LogN), vc.end());

If you are allowed to sort input, you might use std::set_difference : 如果允许对输入进行排序,则可以使用std::set_difference

std::vector<std::string> vc { "ala", "bala", "test", "sample" };
std::vector<std::string> v2 { "test", "bala" };

std::sort(vc.begin(), vc.end());
std::sort(v2.begin(), v2.end());

std::vector<std::string> res;
std::set_difference(vc.begin(), vc.end(),
                    v2.begin(), v2.end(), 
                    std::back_inserter(res));

Demo 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM