如何检测 std::map 循环中的最后一次迭代?

发布于 2024-07-07 11:42:05 字数 383 浏览 7 评论 0原文

我试图找出最好的方法来确定我是否处于地图上循环的最后一次迭代中,以便执行如下操作:

for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
    bool last_iteration;
    // do something for all iterations
    if (!last_iteration) {
        // do something for all but the last iteration
    }
}

似乎有几种方法可以做到这一点:随机访问迭代器, distance 函数等。规范方法是什么?

编辑:地图没有随机访问迭代器!

I'm trying to figure out the best way to determine whether I'm in the last iteration of a loop over a map in order to do something like the following:

for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
    bool last_iteration;
    // do something for all iterations
    if (!last_iteration) {
        // do something for all but the last iteration
    }
}

There seem to be several ways of doing this: random access iterators, the distance function, etc. What's the canonical method?

Edit: no random access iterators for maps!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

一页 2024-07-14 11:42:05

典范? 我不能这么说,但我建议

final_iter = someMap.end();
--final_iter;
if (iter != final_iter) ...

编辑按照KTC.(谢谢!有时你走得太快,会把最简单的事情搞砸......)

Canonical? I can't claim that, but I'd suggest

final_iter = someMap.end();
--final_iter;
if (iter != final_iter) ...

Edited to correct as suggested by KTC. (Thanks! Sometimes you go too quick and mess up on the simplest things...)

反差帅 2024-07-14 11:42:05

从 C++11 开始,您还可以使用 std::next()

   for (auto iter = someMap.begin(); iter != someMap.end(); ++iter) { 
        // do something for all iterations
        if (std::next(iter) != someMap.end()) {
            // do something for all but the last iteration
        }
    }

虽然这个问题是不久前提出的,但我认为值得分享。

Since C++11, you can also use std::next()

   for (auto iter = someMap.begin(); iter != someMap.end(); ++iter) { 
        // do something for all iterations
        if (std::next(iter) != someMap.end()) {
            // do something for all but the last iteration
        }
    }

Although the question was asked a while ago, I thought it would be worth sharing.

断爱 2024-07-14 11:42:05

这看起来是最简单的:

bool last_iteration = iter == (--someMap.end());

This seems like the simplest:

bool last_iteration = iter == (--someMap.end());
墨洒年华 2024-07-14 11:42:05

如果您只想使用 ForwardIterator,这应该可以工作:

for ( i = c.begin(); i != c.end(); ) {
        iterator cur = i++;
        // do something, using cur
        if ( i != c.end() ) {
                // do something using cur for all but the last iteration
        }
}

If you just want to use a ForwardIterator, this should work:

for ( i = c.begin(); i != c.end(); ) {
        iterator cur = i++;
        // do something, using cur
        if ( i != c.end() ) {
                // do something using cur for all but the last iteration
        }
}
桃扇骨 2024-07-14 11:42:05

修改了 Mark Ransom 的,使其实际上按预期工作。

finalIter = someMap.end();
--finalIter;
if (iter != final_iter)

Modified Mark Ransom's so it actually work as intended.

finalIter = someMap.end();
--finalIter;
if (iter != final_iter)
梦一生花开无言 2024-07-14 11:42:05

令人惊讶的是还没有人提到它,但当然 boost 有一些东西;)

Boost.Next(以及等效的 Boost.Prior)

您的示例如下所示:

for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
    // do something for all iterations
    if (boost::next(iter) != someMap.end()) {
        // do something for all but the last iteration
    }
}

Surprised no one mentioned it yet, but of course boost has something ;)

Boost.Next (and the equivalent Boost.Prior)

Your example would look like:

for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
    // do something for all iterations
    if (boost::next(iter) != someMap.end()) {
        // do something for all but the last iteration
    }
}
分开我的手 2024-07-14 11:42:05

以下代码将由编译器进行优化,以便根据性能和 OOP 规则成为此任务的最佳解决方案:

if (&*it == &*someMap.rbegin()) {
    //the last iteration
}

这是 OOP 规则的最佳代码,因为 std::map 有一个特殊的成员函数 rbegin 用于代码如下:

final_iter = someMap.end();
--final_iter;

The following code would be optimized by a compiler so that to be the best solution for this task by performance as well as by OOP rules:

if (&*it == &*someMap.rbegin()) {
    //the last iteration
}

This is the best code by OOP rules because std::map has got a special member function rbegin for the code like:

final_iter = someMap.end();
--final_iter;
邮友 2024-07-14 11:42:05

为什么要努力寻找 EOF,这样你就不会给它一些东西。

简单地,排除它;

for (iter = someMap.begin(); someMap.end() - 1; ++iter) {
    //apply to all from begin to second last element
}

KISS(保持简单)

Why to work to find the EOF so that you dont give something to it.

Simply, exclude it;

for (iter = someMap.begin(); someMap.end() - 1; ++iter) {
    //apply to all from begin to second last element
}

KISS (KEEP IT SIMPLY SIMPLE)

狼性发作 2024-07-14 11:42:05
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <algorithm>

using namespace boost::lambda;

// call the function foo on each element but the last...
if( !someMap.empty() )
{
  std::for_each( someMap.begin(), --someMap.end(), bind( &Foo, _1 ) );
}

使用 std::for_each 将确保循环紧密且准确...请注意函数 foo() 的引入,该函数采用单个参数(类型应与 someMap 中包含的内容匹配)。 此方法还增加了 1 行。 当然,如果 Foo 真的很小,您可以使用 lambda 函数并摆脱对 &Foo 的调用。

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <algorithm>

using namespace boost::lambda;

// call the function foo on each element but the last...
if( !someMap.empty() )
{
  std::for_each( someMap.begin(), --someMap.end(), bind( &Foo, _1 ) );
}

Using std::for_each will ensure that the loop is tight and accurate... Note the introduction of the function foo() which takes a single argument (the type should match what is contained in someMap). This approach has the added addition of being 1 line. Of course, if Foo is really small, you can use a lambda function and get rid of the call to &Foo.

音栖息无 2024-07-14 11:42:05

这个怎么样,没有人提到,但是……

for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
    // do something for all iterations
    if (iter != --someMap.end()) {
        // do something for all but the last iteration
    }
}

这看起来很简单,嗯……

How about this, no one mentioning but...

for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
    // do something for all iterations
    if (iter != --someMap.end()) {
        // do something for all but the last iteration
    }
}

this seems simple, mm...

○愚か者の日 2024-07-14 11:42:05

对于喜欢 C++11 基于范围的循环的人:

    for (const auto& pair : someMap) {
      if (&pair != &*someMap.rbegin()) ...
    }

请注意,此处仅引用类型有效,自动配对 无效

For someone who likes C++11 range-based loop:

    for (const auto& pair : someMap) {
      if (&pair != &*someMap.rbegin()) ...
    }

Notice only reference type works here, not auto pair

凉薄对峙 2024-07-14 11:42:05

一个简单而有效的方法:

  size_t items_remaining = someMap.size();

  for (iter = someMap.begin(); iter != someMap.end(); iter++) {
    bool last_iteration = items_remaining-- == 1;
  }

A simple, yet effective, approach:

  size_t items_remaining = someMap.size();

  for (iter = someMap.begin(); iter != someMap.end(); iter++) {
    bool last_iteration = items_remaining-- == 1;
  }
国际总奸 2024-07-14 11:42:05

完整程序:

#include <iostream>
#include <list>

void process(int ii)
{
   std::cout << " " << ii;
}

int main(void)
{
   std::list<int> ll;

   ll.push_back(1);
   ll.push_back(2);
   ll.push_back(3);
   ll.push_back(4);
   ll.push_back(5);
   ll.push_back(6);

   std::list<int>::iterator iter = ll.begin();
   if (iter != ll.end())
   {
      std::list<int>::iterator lastIter = iter;
      ++ iter;
      while (iter != ll.end())
      {
         process(*lastIter);
         lastIter = iter;
         ++ iter;
      }
      // todo: think if you need to process *lastIter
      std::cout << " | last:";
      process(*lastIter);
   }

   std::cout << std::endl;

   return 0;
}

该程序产生:

 1 2 3 4 5 | last: 6

Full program:

#include <iostream>
#include <list>

void process(int ii)
{
   std::cout << " " << ii;
}

int main(void)
{
   std::list<int> ll;

   ll.push_back(1);
   ll.push_back(2);
   ll.push_back(3);
   ll.push_back(4);
   ll.push_back(5);
   ll.push_back(6);

   std::list<int>::iterator iter = ll.begin();
   if (iter != ll.end())
   {
      std::list<int>::iterator lastIter = iter;
      ++ iter;
      while (iter != ll.end())
      {
         process(*lastIter);
         lastIter = iter;
         ++ iter;
      }
      // todo: think if you need to process *lastIter
      std::cout << " | last:";
      process(*lastIter);
   }

   std::cout << std::endl;

   return 0;
}

This program yields:

 1 2 3 4 5 | last: 6
秋千易 2024-07-14 11:42:05

这是我的优化方案:

iter = someMap.begin();

do {
    // Note that curr = iter++ may involve up to three copy operations
    curr = iter;

    // Do stuff with curr

    if (++iter == someMap.end()) {
        // Oh, this was the last iteration
        break;
    }

    // Do more stuff with curr

} while (true);

Here's my optimized take:

iter = someMap.begin();

do {
    // Note that curr = iter++ may involve up to three copy operations
    curr = iter;

    // Do stuff with curr

    if (++iter == someMap.end()) {
        // Oh, this was the last iteration
        break;
    }

    // Do more stuff with curr

} while (true);
彼岸花似海 2024-07-14 11:42:05

您可以在迭代之前从地图中取出一个元素,然后在循环之外执行“最后一次迭代”工作,然后将元素放回地图中。 这对于异步代码来说非常糟糕,但考虑到 C++ 的其余部分对于并发性来说有多糟糕,我认为这不会成为问题。 :-)

You can just pull an element out of the map prior to iteration, then perform your "last iteration" work out of the loop and then put the element back into the map. This is horribly bad for asynchronous code, but considering how bad the rest of C++ is for concurrency, I don't think it'll be an issue. :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文