【问题标题】:In std::map, get an iterator pointing to the LAST element that is NOT GREATER than key在 std::map 中,获取一个迭代器,该迭代器指向不大于 key 的 LAST 元素
【发布时间】:2018-01-07 15:44:03
【问题描述】:

提问前:我明白std::map::lower_boundstd::map::upper_bound的意思

问题:如何获得指向 LAST 元素且不大于 key 的迭代器。

以下示例显示了lower_bound/upper_bound 的当前行为。

但是,我想要:

  • 传入“20”,返回20
  • 传入“25”,返回20

我怎样才能做到这一点?

#include <iostream>
#include <map>

int main ()
{
  std::map<int,char> mymap;
  std::map<int,char>::iterator itlow,itup;

  mymap[10]='a';
  mymap[20]='b';
  mymap[30]='c';
  mymap[40]='d';
  mymap[50]='e';

  itlow=mymap.lower_bound (20);  // itlow points to 'b'  
  std::cout << "lower_bound for 20:    " << itlow->first << " => " << itlow->second << '\n';

  itup=mymap.upper_bound (20);   // itup points to 'c'
  std::cout << "upper_bound for 20:    " << itup->first << " => " << itup->second << '\n';


  itlow=mymap.lower_bound (25);  // itlow points to 'c'  
  std::cout << "lower_bound for 25:    " << itlow->first << " => " << itlow->second << '\n';

  itup=mymap.upper_bound (25);   // itup points to 'c'
  std::cout << "upper_bound for 25:    " << itup->first << " => " << itup->second << '\n';


  return 0;
}

这是上面代码的执行结果。

lower_bound for 20:    20 => b
upper_bound for 20:    30 => c
lower_bound for 25:    30 => c
upper_bound for 25:    30 => c

【问题讨论】:

  • 为什么不直接使用upper_bound,然后将迭代器减一呢? (你必须检查它是否等于mymap.begin()
  • @rlbond 太棒了!
  • @rlbond 如果你把这个放在答案中,我会投票赞成:-)

标签: c++


【解决方案1】:

荣誉属于@rlbond。

  • 使用upper_bound,然后将迭代器减一;

  • 如果upper_bound返回的迭代器指向map.begin(),则说明map中没有小于参数的元素。

再次感谢

#include <iostream>
#include <map>

int main ()
{
  std::map<int,char> mymap;

  mymap[10]='a';
  mymap[20]='b';
  mymap[30]='c';
  mymap[40]='d';
  mymap[50]='e';

  int nValue = 25;

  std::map<int,char>::const_iterator it=mymap.upper_bound (nValue);
  if(it != mymap.begin())
  {
      it--;
      std::cout << "last element no greater than " << nValue << " is :    " << it->first << " => " << it->second << '\n';
  }
  else
  {
      std::cout << "no element is less than " << nValue << '\n';
  }

  return 0;
}

结果给出:

last element no greater than 25 is :    20 => b

解释:

map.end() 如果没有找到这样的元素会返回,但是指向map.end()的迭代器只要不指向map.begin()仍然可以递减,然后它会指向所需的元素。

两个测试用例:

  • 将nValue改为60并运行代码(此时upper_bound将返回map.end()),你会得到“50 => e”,这是正确的。
  • 注释掉5个map set语句留下一个空map进行测试,那么map.end()和map.begin()是一样的,upper_bound会返回map.end(),会打印“no element小于 XX”。仍然正确。

【讨论】:

  • 很好的答案,但有点不正确。如果不存在满足upper_bound 的值,则返回map.end() NOT map.begin() 请参见en.cppreference.com/w/cpp/container/map/upper_bound
  • @Casey 谢谢,但是......我知道如果没有找到这样的元素, map.end() 将被返回。但是,指向 map.end() 的迭代器仍然可以递减并指向我想要的元素。例如,将 nValue 更改为 60 并运行代码,您将得到“50 => e”,这是正确的。即使在空地图上,它也会打印“no element is less than XX”,仍然正确。
【解决方案2】:
template<class It>
std::optional<It> last(std::pair<It,It> range){
  if (range.first==range.second) return {};
  return std::prev(range.second);
}
template<class It>
std::optional<It> last(It b, It e){
  return last(std::make_pair(std::move(b),std::move(e)));
}
template<class C>
auto last(C& c){
  using std::begin; using std::end;
  return last(begin(c), end(c));
}

然后:

auto r=last(mymap.begin(), mymap.upper_bound(20));
if (r) std::cout <<**r;
else std::cout << "nothing";
std::cout <<'\n';

【讨论】:

    猜你喜欢
    • 2011-02-11
    • 2016-10-31
    • 2018-04-13
    • 2011-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    • 2016-02-12
    相关资源
    最近更新 更多