Frage

Ich versuche, den besten Weg, um herauszufinden, ob ich in der letzten Iteration einer Schleife über eine Karte, um mich so etwas wie die folgenden Funktionen ausführen:

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

Es scheint mehrere Möglichkeiten, dies zu tun zu sein: random access Iteratoren, die distance Funktion usw. Was die kanonische Methode ist

Edit: keine Random Access-Iteratoren für Karten

War es hilfreich?

Lösung

Canonical? Das kann ich nicht behaupten, aber ich würde vorschlagen,

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

Edited zu korrigieren, wie durch KTC . (Danke! Manchmal gehen Sie zu schnell und mess up auf die einfachsten Dinge ...)

Andere Tipps

Da C ++ 11, können Sie auch 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
        }
    }

Obwohl die Frage vor einer Weile gefragt wurde, dachte ich, es sich wert sein würde.

Dies scheint die einfachste:

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

Wenn Sie nur ein ForwardIterator verwenden möchten, sollte diese Arbeit:

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

Modifizierte Mark Ransom so ist es tatsächlich wie vorgesehen.

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

überraschte niemand es noch erwähnt, aber natürlich Auftrieb hat etwas;)

Boost.Next (und die Äquivalent Boost.Prior)

Ihr Beispiel würde wie folgt aussehen:

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

Der folgende Code würde durch einen Compiler optimiert werden, so dass die beste Lösung für diese Aufgabe durch Leistung als auch durch OOP Regeln sein:

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

Dies ist der beste Code von OOP Regeln, weil std :: map eine spezielle Memberfunktion rbegin für den Code erhalten hat, wie:

final_iter = someMap.end();
--final_iter;
#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 wird gewährleistet, dass die Schleife ist dicht und präzise ... Beachten Sie die Einführung der Funktion foo (), die ein einzelnes Argument (der Typ sollte dem entsprechen, was in someMap enthalten ist). Dieser Ansatz hat die zusätzliche Zugabe von 1 Linie ist. Natürlich, wenn Foo wirklich klein sind, können Sie eine Lambda-Funktion verwenden und die Beseitigung des Anrufs Foo & erhalten.

Warum die EOF zu finden arbeiten, so dass Sie etwas, um es nicht geben.

Einfach gesagt, es auszuschließen;

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

KISS (Keep it SIMPLY SIMPLE)

Ein einfacher, aber effektiver Ansatz:

  size_t items_remaining = someMap.size();

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

Hier ist meine optimierte nehmen:

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);

Wie wäre es damit, niemand zu erwähnen, aber ...

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

Dies scheint einfach, mm ...

Volles Programm:

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

Dieses Programm liefert:

 1 2 3 4 5 | last: 6

Sie können nur ein Element aus der Karte vor der Iteration ziehen, dann „letzte Iteration“ perform aus der Schleife arbeitet und dann das Element setzen in die Karte. Das ist schrecklich schlecht für asynchronen Code, aber wenn man bedenkt, wie schlecht der Rest von C ++ für Nebenläufigkeit ist, ich glaube nicht, es wird ein Thema sein. : -)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top