如何在std :: set中给定下限和上限的地图中获取一系列值?

时间:2016-11-08 10:46:51

标签: c++ set containers std

说我有以下代码

#include <iostream>
#include <set>

int main ()
{
  std::set<int> myset;
  int inf, sup;

  inf = 25; sup = 60;
  for (int i=1; i<10; i++) myset.insert(i*10); // 10 20 30 40 50 60 70 80 90

  return 0;
}

我试图弄清楚标准库是否提供了任何方法或方法组合,这些方法允许我获得两个迭代器it_l, it_u,以便覆盖范围[inf,sup]。我试过使用lower_bound,upper_bound,但我误解了它们是如何工作的。这个想法是避免写循环(因为我知道我可以为这个任务编写自己的函数,但也许有一些我不知道的替代方法。)

更新:预期输出的一些示例(在我的示例中)

inf =25; sup = 60我希望{30,40,50,60}

如果改为

inf=30; sup = 60我希望{30,40,50,60}

如果

inf=25; sup = 65我希望{30,40,50,60}

显然存在误解,或者也许是我,我没有正确表达我想做的事情。

当我说inf和sup时,请将它们视为实际间隔的极值。一旦你做了这样的假设,我想要检索的是区间[inf,sup]和由set对象指定的离散集之间的交集。我刚刚说的和我的例子之间是否存在一些矛盾?

允许A={10 20 30 40 50 60 70 80 90}B1=[25,60]B2=[30,60]B3=[25,65]

对于每个i=1,2,3 ABi之间的交集给出了我在示例中所说的内容。

4 个答案:

答案 0 :(得分:4)

这对我来说很好用:

#include <iostream>
#include <set>

template <typename T>
std::pair<typename std::set<T>::const_iterator, typename std::set<T>::const_iterator>
infsup(const std::set<T>& set, const T& inf, const T& sup)
{
  return std::make_pair(set.lower_bound(inf), set.upper_bound(sup));
}

int main ()
{
  std::set<int> myset;
  int inf, sup;

  for (int i=1; i<10; i++) myset.insert(i*10); // 10 20 30 40 50 60 70 80 90

  for (auto its = infsup(myset, 30, 60); its.first != its.second; ++its.first)
  {
    std::cout << " " << *its.first; // 30 40 50 60
  }
  std::cout << std::endl;

  for (auto its = infsup(myset, 25, 65); its.first != its.second; ++its.first)
  {
    std::cout << " " << *its.first; // 30 40 50 60
  }
  std::cout << std::endl;

  return 0;
}

inf使用lower_bound意味着启动迭代器将指向第一个不小于inf 的元素,因此满足条件想要达到范围的低端。

sup使用upper_bound意味着结束迭代器将指向_第一个大于sup _的元素。请注意,在C ++中,结束迭代器始终将指向范围的末尾,因此将包含sup

编辑以反映评论中的讨论(感谢@Useless指出):请注意,这适用于空结果范围,例如。

  • infsup都小于集合
  • 中的最小元素时
  • 当两者都大于最大元素时
  • 当[inf,sup]中没有元素时(在您的示例中,说inf=25, sup=29

但是如果你选择inf > sup以便返回的迭代器引用不同的元素,那么its.first > its.second会导致for循环(就像我上面写的那样)失败。因此,您需要确保inf <= sup(就像您可能正在编写的任何其他for循环一样)。

答案 1 :(得分:1)

看起来你只想要这个:

auto it_l = myset.lower_bound(inf);
auto it_u = myset.lower_bound(sup + 1);

通过这种方式,您将获得半开的时间间隔[it_l, it_u),使其中的所有元素i都来自myset并且是inf <= i <= sup(即恰恰是您想)。半开放迭代器间隔是整个标准库的工作区域,所以你应该没问题。

答案 2 :(得分:0)

C ++适用于半开范围。也就是说,[inf, sup),永远不会[inf, sup]。标准库很好地支持半开放式习语:只需使用std::set::lower_boundstd::set::upper_bound。 (不是std::upper bound等)。封闭范围不是,如果你坚持使用它,你就是你自己。我建议采用标准方式并在任何地方切换到半开放范围。

答案 3 :(得分:0)

不清楚为什么你说上限和下限不能做你想做的事。

lower_bound将返回指向您要查找的第一个元素的迭代器(第一个元素不小于参数)

upper_bound为你提供了大于参数的第一个元素(在你的例子中为70),但是stl迭代器是如何工作的,结束点是一个超出最后一个元素。

如果您真的需要副本,可以使用这两个迭代器制作元素的副本 - 但您也可以使用它们来访问原始集合的元素 - 并且该范围将包括60而不是70示例