【问题标题】:How to check if an erase-remove operation has been successful?如何检查擦除删除操作是否成功?
【发布时间】:2017-05-18 08:43:28
【问题描述】:

这是我第一次使用这个习语,我有一个向量v1,其中元素必须是另一个向量v2 中元素的子集。现在,将v1 和v2 想象为集合,如果v1[i] 在v2 中不存在,我想执行v2-v1 并抛出异常(对于任何有意义的i)。

我想出了这个:

std::vector<T> v1;
std::vector<T> v2;
//fill v1, v2 somehow
for(size_t i=0; i<v1.size(); i++){
  v2.erase(std::remove(v2.begin(), v2.end(), v1[i]), v2.end());
  if(/*erase option failed because v1[i] doesn't exists in v2*/)
    throw std::runtime_exception (std::to_string(i)+"-th in v1 doesn't exists in v2!");
}

如何填写if 条件?

【问题讨论】:

  • 使用std::includes,如果向量是可以排序的。
  • @manni66 我指定它们没有排序,因为它们不能排序(必须保留顺序)
  • 如果有一百万个项目,将两个向量按值传递给一个函数,std::sort 这些临时向量,然后调用类似std::mismatch 的函数可能会更有效。您的代码将在未排序的数据上循环 10^12 次迭代,而对一百万个项目的两个临时副本进行排序所需的时间要少得多。
  • @PaulMcKenzie 感谢您的回答。事实并非如此,我们正在谈论v1 中的数千个元素。对于代码的这个特定部分(效率不是优先级),我更喜欢保持简单明了的代码。我认为仅仅因为我们使用 C++ 并不意味着我们必须使用最有效的解决方案总是,你同意吗? ;)
  • bool isDifferent(vector&lt;T&gt; v1, vector&lt;T&gt; v2); 和函数内部有什么不清楚的地方,sort 并调用 std::equal 或 std::mismatch?查看您的代码,需要查看 2 到 3 次才能弄清楚它在做什么(它不是自我记录的)。 Scott Parent 在他的许多优秀视频中讨论了这一点,其中编写手动编码的for 循环不如使用各种算法函数来完成这项工作有利。

标签: c++ erase-remove-idiom


【解决方案1】:

只需检查是否删除了任何元素:

const auto orig_size = v2.size();
v2.erase(std::remove(v2.begin(), v2.end(), v1[i]), v2.end());
if (v2.size() == orig_size)

或将其拆分(没有什么会强迫您在单个语句中执行删除和擦除):

const auto last = std::remove(v2.begin(), v2.end(), v1[i])
if (last == v2.end())
  throw std::runtime_exception (std::to_string(i)+"-th in v1 doesn't exists in v2!");
v2.erase(last, v2.end());

如果您对两个向量进行排序并使用算法一起遍历它们,您可以使代码更加高效。您当前的代码为 O(n²),因为它会在整个 v2 中搜索 v1 中的每个元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-06
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多