Ich arbeite mich gerade durch Effective STL. Punkt 5 legt nahe, dass es normalerweise vorzuziehen ist, Bereichselementfunktionen gegenüber ihren Einzelelementgegenstücken zu verwenden. Ich möchte derzeit alle Werte in einer Karte (dh ich brauche die Schlüssel nicht) auf einen Vektor kopieren.
Was ist der sauberste Weg, dies zu tun?
c++
stl
containers
Gilad Naor
quelle
quelle
Antworten:
Sie können einen Bereich hier nicht einfach verwenden, da sich der Iterator, den Sie von einer Karte erhalten, auf ein std :: pair bezieht, wobei sich die Iteratoren, die Sie zum Einfügen in einen Vektor verwenden würden, auf ein Objekt des im Vektor gespeicherten Typs beziehen (wenn Sie den Schlüssel wegwerfen) kein Paar.
Ich glaube wirklich nicht, dass es viel sauberer wird als das Offensichtliche:
was ich wahrscheinlich als Vorlagenfunktion neu schreiben würde, wenn ich es mehr als einmal verwenden würde. Etwas wie:
quelle
Sie könnten wahrscheinlich
std::transform
für diesen Zweck verwenden. Ich würde vielleicht die Neils-Version bevorzugen, je nachdem, was besser lesbar ist.Beispiel von xtofl (siehe Kommentare):
Sehr allgemein, denken Sie daran, ihm Anerkennung zu schenken, wenn Sie es nützlich finden.
quelle
Alte Frage, neue Antwort. Mit C ++ 11 haben wir die schicke neue for-Schleife:
wobei Schemata ein
std::map
und Namen ein iststd::vector
.Dies füllt das Array (Namen) mit Schlüsseln aus der Karte (Schemata); Ändern Sie
s.first
zus.second
, um ein Array von Werten abzurufen.quelle
const auto &s
reserve()
Sie hinzu und Sie erhalten einen weiteren Leistungsgewinn. Mit dem Aufkommen von C ++ 11 sollte dies nun die akzeptierte Lösung sein!Wenn Sie die Boost-Bibliotheken verwenden , können Sie mit boost :: bind wie folgt auf den zweiten Wert des Paares zugreifen:
Diese Lösung basiert auf einem Beitrag von Michael Goldshteyn auf der Boost-Mailingliste .
quelle
Es tut mir leid, dass ich keine Erklärung hinzugefügt habe - ich dachte, dass der Code so einfach ist, dass keine Erklärung erforderlich ist. So:
Diese Funktion ruft
unaryOperation
jedes Element aus deminputIterator
Bereich (beginInputRange
-endInputRange
) auf. Der Wert der Operation wird in gespeichertoutputIterator
.Wenn wir die gesamte Karte durcharbeiten möchten, verwenden wir map.begin () und map.end () als Eingabebereich. Wir möchten unsere Kartenwerte in einem Vektor speichern - daher müssen wir back_inserter für unseren Vektor verwenden :
back_inserter(your_values_vector)
. Der back_inserter ist ein spezieller outputIterator, der neue Elemente am Ende einer bestimmten Sammlung (als Paremeter) pusht. Der letzte Parameter ist unaryOperation - es wird nur ein Parameter verwendet - der Wert von inputIterator. Wir können also Lambda: verwenden[](auto &kv) { [...] }
, wobei & kv nur eine Referenz auf das Paar des Kartenelements ist. Wenn wir also nur Werte von Kartenelementen zurückgeben möchten, können wir einfach kv.second zurückgeben:Ich denke, das erklärt alle Zweifel.
quelle
Mit Lambdas kann man folgendes ausführen:
quelle
Hier ist was ich tun würde.
Außerdem würde ich eine Vorlagenfunktion verwenden, um die Konstruktion von select2nd zu vereinfachen.
quelle
Eine Möglichkeit ist die Verwendung des Funktors:
quelle
Warum nicht:
Verwendung:
auto vec = MapValuesAsVector (anymap);
quelle
Ich dachte es sollte sein
quelle
Wir sollten die Transformationsfunktion aus dem STL-Algorithmus verwenden. Der letzte Parameter der Transformationsfunktion kann ein Funktionsobjekt, ein Funktionszeiger oder eine Lambda-Funktion sein, die ein Kartenelement in ein Vektorelement konvertiert. Diese Fallkarte enthält Elemente mit einem Typpaar, die in ein Element mit dem Typ int für den Vektor konvertiert werden müssen. Hier ist meine Lösung, dass ich die Lambda-Funktion verwende:
quelle
Überrascht, dass niemand die naheliegendste Lösung erwähnt hat , verwenden Sie den Konstruktor std :: vector.
quelle