如何在std::set中获得给定下界和上界的映射中的值范围?

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

本文关键字:映射 范围 std set      更新时间:2023-10-16

假设我有以下代码

#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 I expect {30,40,50,60}

如果

inf=25; sup = 65 I expect {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之间的交集正好给出了我在我的例子中所说的。

这对我来说很好:

#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意味着end迭代器将指向_第一个大于sup _的元素。请注意,在c++中,end迭代器总是指向刚好超出范围的end,因此将包含sup

编辑以反映评论中的讨论(感谢@Useless指出这一点):注意,这对空结果范围有效,例如

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

但是,如果您选择inf > sup,以便返回的迭代器指向不同的元素,则选择its.first > its.second,这将使for循环(如上所述)失败。因此,确保inf <= sup(就像您可能编写的任何其他for循环一样)由您决定。

看来你只是想要这个:

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

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

我不知道为什么你说的上限和下限不能做你想做的。

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

upper_bound给你第一个大于参数的元素(在你的例子中是70),但这就是STL迭代器的工作方式,end指向one- beyonthe -last-element。

这两个迭代器可以用来复制元素,如果你真的想要一个副本——但你也可以用它们来访问原始集合的元素——在你的例子中,这个范围包括60,而不是70。

c++使用半开范围。也就是[inf, sup),而不是[inf, sup]。标准库很好地支持半开放范围的习惯用法:只需使用std::set::lower_boundstd::set::upper_bound。(不是std::upper bound等)。如果你坚持要用,那就只能靠你自己了。我建议采用标准方法,并在所有地方切换到半开放范围。