2014-06-08 8 views
6

Sagen wir, ich bin eine Initialisierung vector<vector<string>> wie so:Merge vector und initializer_list bei der Initialisierung des Vektors <vector<T>>?

vector<vector<string>> v; 
v = {{ 
    {"a", "b", "c"}, 
    {"aa", "bb"}, 
    {"xyz", "yzx", "zxy"}, 
    {} 
}}; 

Jetzt möchte ich nehme an eine bereits bestehende vector<string> zu einigen v ‚s Elemente anzuhängen. Wie so:

vector<string> suffix {{"1", "2", "3"}}; 
vector<vector<string>> v; 
v = {{ 
    {"a", "b", "c"} + suffix, 
    {"aa", "bb"}, 
    {"xyz", "yzx", "zxy"} + suffix, 
    {} 
}}; 

Diese Syntax funktioniert natürlich nicht, weil operator+ nicht so definiert ist.

Ich verstehe, dass es möglich ist, v den ersten Weg zu konstruieren und dann

vector<int> indices = {0, 2}; 
for(int i: indices) 
    v[i].insert(v[i].end(), suffix.begin(), suffix.end()); 

schreiben Aber das ist nicht praktisch, weil ich mehrere suffix Vektoren aufweisen, die auf beliebige v[i] angebracht sind. Ich möchte die suffix zusammen mit der Initialisierung der v[i] so sinnvoll macht und ich muss Indizes nicht verschieben, wenn ich Elemente aus v Initialisierung hinzufügen/entfernen.

Antwort

3

Eine mögliche Lösung ist die Verwendung einer Hilfsfunktion, die das Anhängen durchführt.

vector<string> appendStrings(vector<string>&& s1, vector<string> const& s2) 
{ 
    s1.insert(s1.end(), s2.begin(), s2.end()); 
    return s1; 
} 

Und verwenden Sie es, um die Variable zu initialisieren.

vector<string> suffix {{"1", "2", "3"}}; 
vector<vector<string>> v = {{ 
    appendStrings({"a", "b", "c"}, suffix), 
    {"aa", "bb"}, 
    appendStrings({"xyz", "yzx", "zxy"}, suffix), 
    {} 
}}; 

aktualisieren

Eine effizientere Implementierung von appendStrings (Dank @Yakk):

vector<string> appendStrings(initializer_list<char const*>&& s1, 
          vector<string> const& s2) 
{ 
    vector<string> ret. 
    ret.reserve(s1.size() + s2.size()); 
    for (auto item : s1) { 
     ret.emplace_back(item); 
    } 
    ret.insert(ret.end(), s2.begin(), s2.end()); 
    return ret; 
} 
+0

Wenn 's1' eine Initialisiererliste ist, eine Zuordnung vermeiden. Wenn Sie sich zurück bewegen, vermeiden Sie eine andere. – Yakk

+0

@Yakk, ich glaube, ich verstehe den 'move' Return-Teil, aber ich habe keine Ahnung, was du mit dem ersten Teil deines Kommentars meinst. –

+0

Ändern Sie den Vektor && 'in' std :: initializer_list '(oder' T'). Erstellen Sie einen "Vektor" innerhalb dieser "Reserven" genug für diese Liste und den zweiten "Vektor", laden Sie sie dann hoch und kehren Sie zurück. Erhalten Sie 1 Speicherzuweisung, plus 1 pro 'std :: string 'zugewiesen, anstelle von Ihrem ... 3? plus 2 pro 'std :: string' (' move' lässt es auf 2 + 1 fallen). Nur Mikrooptimierung. – Yakk

Verwandte Themen