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;
我需要删除items
中removeItems
中的值,同时保留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
items
或 removeItems
中的元素数将在 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_if
和std::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++ 删除存在于另一个向量中的向量项,同时保留顺序的主要内容,如果未能解决你的问题,请参考以下文章