C++ 删除存在于另一个向量中的向量项,同时保留顺序

Posted

技术标签:

【中文标题】C++ 删除存在于另一个向量中的向量项,同时保留顺序【英文标题】:C++ Remove vector items that exist in another vector WHILE retaining order 【发布时间】:2020-06-05 15:33:39 【问题描述】:
std::vector<int> items = 1, 2, 3, 4, 5;
std::vector<int> removeItems = 2, 4;

我需要删除itemsremoveItems 中的值,同时保留items 的顺序。像这样的:

items.remove(removeItems);

输出

项目 = 1, 3, 5

是否有任何内置的向量方法可以实现这一点?我还没有找到任何接受另一个要删除的项目向量。如果没有,实现这一目标的最有效方法是什么?

编辑

Erasing elements from a vector 这篇文章是指一次删除一个项目,我希望以更紧凑的方式一次删除一大堆

for(num in removeItems) 
    items.erase(std::remove(items.begin(), items.end(), num), items.end())

因为这种删除项目的方式肯定是非常低效的,因为对于removeItems 中的每个项目,您必须检查整个items 向量两次(removeItems.size()

编辑 2

itemsremoveItems 中的元素数将在 0-10000 范围内

【问题讨论】:

***.com/a/347478/783510 我想你正在寻找所谓的“删除/擦除”成语 @PhilippClaßen 否,因为他们一次删除单个成员。我希望一次完成所有工作 “我希望以一种更紧凑的方式一次删除一大堆”它只是组合......把它放在一个函数中!! 【参考方案1】:

最有效的一般形式是将removeItems 变成一个无序集合,然后通过检查成员资格从items 中删除元素。

std::unordered_set<int> removeSet(removeItems.begin(), removeItems.end());
items.erase(std::remove_if(items.begin(), items.end(), [&](int x) 
    return removeSet.count(x) != 0;
), items.end());

如果removeItems 很小,则线性扫描可能比将其转换为无序集更快。对于大的removeItems,上面的方法是最有效的,除非它有非常特殊的形式(比如只有小元素)。

如果两个数组都已排序(就像在您的示例中一样,假设这不是巧合),您可以做得比上述更好。

【讨论】:

老实说,removeItems 这么小,坚持使用向量并执行 O(n*m) 搜索序列可能会更快。跨度> @AsteroidsWithWings 可能,但我不知道 真实 removeItems 有多大。此解决方案随items/removeItems 的任意数量线性缩放,而保持向量是二次的。 是的,它可以扩展,但在您要删除许多元素之前,实际性能会更差。在编写代码时,我们应该考虑现实而不仅仅是理论上的扩展。至少答案应该提到这一点。 @cdhowie 不需要吗? 非常感谢!工作就像一个魅力,我有一种预感,可能与它有关!【参考方案2】:

您可以在std::remove_ifstd::find 的帮助下申请erase-remove idiom。

std::vector<int> items = 1, 2, 3, 4, 5;
std::vector<int> removeItems = 2, 4;
items.erase(std::remove_if(std::begin(items),
                           std::end(items),
                           [&removeItems](auto i)  return std::find(std::begin(removeItems), std::end(removeItems), i) != std::end(removeItems); ),
            std::end(items));

注意std::remove_if只是将要移除的元素移到vector的后面;这些元素稍后会被std::vector::erase 删除。

【讨论】:

以上是关于C++ 删除存在于另一个向量中的向量项,同时保留顺序的主要内容,如果未能解决你的问题,请参考以下文章

需要 7 个并行向量的 C++ 程序(用于学校)存在问题

C++:如何检测向量中的重复项并打印一份?

C++ 大向量搜索项

C++ STD 容器:std::vector - 有没有办法清除向量并保留存储分配?

如何从多个向量中删除相同的行位置?

从向量中删除对象会破坏 C++ 中另一个对象中的对象