2013-09-05 14 views
5

Beachten Sie Folgendes zur Karte:C++ std eine Liste kopieren

struct A 
{ 
    int i; 
    double d; 
    std::string s; 
}; 

std::list<A> list_A; 

Ich mag würde alle Elemente list_A auf eine Karte kopieren, so dass jedes Paar in der Karte eines Elements aus list_A bestehen wird als Wert und seine Zeichenfolge s als Schlüssel. Gibt es eine elegantere Methode, als die Liste durchzulaufen und jedes Element zusammen mit seiner Zeichenfolge als Schlüssel in die Karte einzufügen?

+5

Für mich ist das Looping die am besten lesbare und unterstützungsfähigste Lösung. –

+1

Sie könnten etwas mit ['std :: transform'] (http://en.cppreference.com/w/cpp/algorithm/transform) tun. – juanchopanza

+0

Sie können eine standardmäßige For- oder Entfernungs-basierte Schleife verwenden. Wenn Sie stattdessen einen Standardbibliotheksalgorithmus verwenden, schreiben Sie den gleichen Schleifenkörper und packen ihn in ein Funktionsobjekt oder Lambda, um ihn an den Algorithmus zu übergeben. Für etwas so einfaches halte ich eine 'range-based for'-Schleife für" besser ". – Blastfurnace

Antwort

6

Dies sollten Sie die Vorstellung davon, wie transform zu verwenden:

std::pair<std::string, A> pairify(const A& a) { return std::make_pair(a.s, a); } 

std::transform(list.begin(), list.end(), std::inserter(map, map.end()), pairify); 

Die reason to use the inserter ist:

Ein Einsatz interator eine spezielle Art von Output-Iterator ist ausgelegt Algorithmen zu ermöglichen Diese überschreiben normalerweise Elemente (z. B. Kopie), um stattdessen neue Elemente automatisch an einer bestimmten Position im Container einzufügen.

+0

Und es funktioniert gut :) –

+0

I Ich weiß, dass ich nicht nach Effizienz gefragt habe, aber ich bin neugierig: Ist dieser Weg auch effizienter, als alle Elemente durchzugehen und sie in die Karte einzufügen? – Subway

1

Sorry antwortete zu schnell letztes Mal ohne Details, hier ist ein kompilierbarer Code.

struct A 
{ 
    int i; 
    double d; 
    std::string s; 
}; 

std::list<A> list_A; 

std::pair<std::string, A> convert(const A &x) { 
    return make_pair(x.s,x); 
} 

int main() { 

    std::map<std::string,A> out; 

    std::transform(list_A.begin(), list_A.end(), std::inserter(out,out.end()),convert); 

} 
+0

Nein ... Erstens, Karte benötigt zwei Vorlagenparameter und zweitens können Sie Karte nicht initialisieren, um die gleiche Größe der Liste zu haben. – LarryPel

+0

Außerdem wird Transformation etwas wie tun: * map_iterator = functionToCopyStructToList(); und du kannst einen Map-Iterator nicht so "zuweisen" ... dieser Code wird nicht kompiliert – LarryPel

+0

Beide von euch haben Recht, ich habe nur die Umrisse zum ersten Mal ohne alle Details gegeben – jayadev

0

speichere ich kann es in einer set: Auf diese Weise wäre es nicht Datenduplizierung in der Karte sein (s selbst):

struct A 
{ 
    bool operator < (const A& r_) const { return (s < r_.s); } 
    int i; 
    double d; 
    std::string s; 
}; 

std::list<A> list_A; 
std::set<A> set_A; 

for (std::list<A>::const_iterator itr = list_A.begin(); itr != list_A.end(); ++itr) { 
    if (! set_A.insert(*itr).second) { 
     // Handle duplicated elements 
    } 
} 

ich die Schleife halten kann: auf diese Weise Sie umgehen konnte Dupliziert Elemente korrekt.

0

Wenn Sie C++ 11 Sie Lambda-Funktion mit Capture verwenden können:

std::map<std::string, A> m; 
std::list<A> l; 
std::for_each(l.begin(), l.end(), 
       [&](const A& a) { 
        m.insert(std::make_pair(a.s, a)); 
       }); 
4

Ich liebe Standard-Bibliothek Algorithmen und Lambda-Ausdrücke, aber es ist nicht viel einfacher als:

for (const A& value : list_A) { 
    map_A.insert(std::make_pair(value.s, value)); 
} 

Die anderen Methoden machen das Äquivalent dieses Codes und diese Schleife ist lesbar und genauso schnell.

+0

Ich denke, dieser Typ ist nicht der Einfachheit halber :). –

Verwandte Themen