29

次のようなことを行うために、マップ上のループの最後の反復にいるかどうかを判断するための最良の方法を見つけようとしています。

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関数など。正規の方法は何ですか?

編集:マップのランダムアクセスイテレータはありません!

4

15 に答える 15

28

正規?私はそれを主張することはできませんが、私はお勧めします

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

KTCの提案に従って修正するために編集されました(ありがとう! ときどき速すぎて、最も単純なことを台無しにしてしまうこともあります...)

于 2008-09-29T22:49:41.440 に答える
23

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

少し前に質問されましたが、共有する価値があると思いました。

于 2015-12-11T11:13:35.823 に答える
14

これは最も単純なようです:

bool last_iteration = iter == (--someMap.end());
于 2008-09-29T22:47:19.857 に答える
10

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
        }
}
于 2008-09-30T11:54:13.757 に答える
6

まだ誰もそれについて言及していないことに驚いたが、もちろんブーストには何かがある;)

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
    }
}
于 2009-01-30T10:28:32.920 に答える
6

Mark Ransom を変更して、実際に意図したとおりに動作するようにしました。

finalIter = someMap.end();
--finalIter;
if (iter != final_iter)
于 2008-09-29T22:57:57.367 に答える
3

次のコードはコンパイラーによって最適化されるため、パフォーマンスとOOPルールによってこのタスクに最適なソリューションになります。

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

std :: mapには、次のようなコード用の特別なメンバー関数rbeginがあるため、これはOOPルールによる最良のコードです。

final_iter = someMap.end();
--final_iter;
于 2011-12-08T12:47:57.817 に答える
3

EOFに何かを与えないように、EOFを見つけるために作業するのはなぜですか。

単純に除外します。

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

キス (KEEP IT SIMPLY SIMPLE)

于 2013-04-06T05:48:13.893 に答える
1
#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 が非常に小さい場合は、ラムダ関数を使用して &Foo の呼び出しを取り除くことができます。

于 2008-09-30T02:08:37.047 に答える
1

これはどうですか、誰も言及していませんが...

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

これは単純に思えます...

于 2015-11-02T10:34:30.807 に答える
0

シンプルでありながら効果的なアプローチ:

  size_t items_remaining = someMap.size();

  for (iter = someMap.begin(); iter != someMap.end(); iter++) {
    bool last_iteration = items_remaining-- == 1;
  }
于 2008-09-29T23:01:10.057 に答える
-1

これが私の最適化されたテイクです:

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);
于 2008-10-01T05:10:19.223 に答える
-1

完全なプログラム:

#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
于 2008-09-29T23:20:15.813 に答える
-2

反復の前に要素をマップから引き出し、ループから「最後の反復」作業を実行してから、要素マップに戻すことができます。これは非同期コードにとっては非常に悪いことですが、C++ の残りの部分が同時実行性に対していかに悪いかを考えると、それが問題になることはないと思います。:-)

于 2008-09-29T22:47:57.453 に答える