【问题标题】:Remove elements from map with keys not containing in another vector使用不包含在另一个向量中的键从地图中删除元素
【发布时间】:2014-11-30 11:15:02
【问题描述】:

给定一个 stl 容器,比如 std::map:

std::map<int, CustomClass> some_container;
std::vector<int> real_objects; 

如何正确有效地从 some_container 映射中删除每个元素,其中键不在 real_objects 向量中?地图是此类任务的最佳容器吗?

【问题讨论】:

  • 您可以尝试使用 std::remove_if() 和适当的 lambda 进行一些实现。
  • 我想说,首先在地图和向量的键之间做一个设置差异,然后删除剩下的。

标签: c++ map stl


【解决方案1】:

我的第一直觉是批量擦除大块非真实对象:

// Assuming real_objets is sorted (otherwise sort it)

auto first = some_container.begin();

for(int i : real_objects) {
  // end of the chunk to erase is the place where i could be
  // inserted without breaking the order
  auto last = some_container.lower_bound(i);

  some_container.erase(first, last);

  // if i is a key in the container, skip that element
  if(last != some_container.end() && last->first == i) {
    ++last;
  }

  first = last;
}

// and in the end, kill stuff that comes after real_objects.back()
some_container.erase(first, some_container.end());

这具有运行时复杂度 O(n * log(m)),其中 n 是 real_objects.size(),m 是 some_container.size(),这意味着如果 some_containerreal_objects 大得多,它的性能最好。否则,由于可以在线性时间内迭代 std::map,因此您可以同步遍历并按顺序删除差异:

// again, sort real_objects.
if(!some_container.empty()) { // else there's nothing to do
  auto ir  = real_objects.begin();
  auto ire = std::lower_bound(real_objects.begin(),
                              real_objects.end  (),
                              some_container.rbegin()->first);
  auto is  = some_container.begin();

  for(;;) {
    // find the next place where the real_objects and the keys of some_container don't match
    auto p = std::mismatch(ir, ire, is, [](int i, std::pair<int, int> const &p) { return i == p.first; });

    if(p.first  == real_objects  .end() ||
       p.second == some_container.end())
    {
      // upon reaching the end, remove all that comes after the
      // end of real_objects (if anything)
      some_container.erase(p.second, some_container.end());
      break;
    } else if(*p.first < p.second->first) {
      // if there's something in real_objects that's not in
      // some_container, skip it
      ++p.first;
    } else {
      // otherwise there's something in some_container that's
      // not in real_objects, so delete it.
      p.second = some_container.erase(p.second);
    }

    ir = p.first;
    is = p.second;
  }
}

这具有运行时复杂度 O(max(n, m)),因此如果 some_containerreal_objects 几乎匹配,它应该会表现良好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-07
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 1970-01-01
    相关资源
    最近更新 更多