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

How Can I get a range of values in a map for given lower bound and upper bound in an std::set?

假设我有以下代码

#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] 与集合对象指定的离散集合之间的交集。我刚才说的和我举的例子有矛盾吗?

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

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

看来你只是想要这个:

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

这样,您将得到半开区间 [it_l, it_u),其中所有元素 i 来自 myset 并且是 inf <= i <= sup(即恰好你想要什么)。半开迭代器区间是整个标准库都使用的,所以你应该没问题。

C++ 使用半开范围。也就是说,[inf, sup),永远不会[inf, sup]。标准库很好地支持半开范围惯用语:只需使用 std::set::lower_boundstd::set::upper_bound。 (不是 std::upper bound 等)。封闭式的不行,非要用就得靠自己了。我建议采用标准方式并在任何地方切换到半开范围。

这对我来说很好用:

#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;
}

Using lower_bound for inf 表示起始迭代器将指向第一个不小于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 循环一样)。

不清楚为什么说上限和下限不是你想要的。

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

upper_bound 为您提供大于参数的第一个元素(在您的示例中为 70),但这就是 stl 迭代器的工作方式,端点指向最后一个元素之外的一个元素。

如果你真的想要一个副本,这 2 个迭代器可用于制作元素的副本 - 但你也可以只使用它们来访问原始集合的元素 - 该范围将包括 60 但不包括 70在你的例子中。