C ++ hängt einen Vektor an einen anderen an

8

Ich verstehe völlig, dass diese Frage viel gestellt wurde, aber ich frage nach einer bestimmten Variante und mein Such-foo hat aufgegeben, da ich nur Algorithmen gefunden habe, die eine existierende anhängen Vektor zu einem anderen, aber nicht einer von einer Funktion zurückgegeben.

Ich habe diese Funktion, die alle Dateien in einem Verzeichnis auflistet:

%Vor%

das sich intern (für Unterverzeichnisse) aufrufen kann.

Ich brauche eine kurze Möglichkeit, den zurückgegebenen Wert an den Vektor des Aufrufers anzufügen. Ich habe so etwas im Kopf (aber natürlich existiert es nicht :():

%Vor%

Ich befürchte, dass das Speichern des Rückgabewerts und das Einfügen in die Dateiliste zu einer schlechten Performance führen würde. Was ich meine, ist dies:

%Vor%

Danke!

PS: Ich zwinge mich nicht dazu, Vektor zu verwenden, irgendeinen anderen Container, der gleich gut funktioniert und verhindern kann, dass der potentielle große Kopiervorgang für mich in Ordnung ist.

    
rubenvb 20.07.2010, 19:20
quelle

10 Antworten

8

Wenn Sie in der Lage sind, scanDir zu ändern, machen Sie eine (Template-) Funktion, die einen Ausgabe-Iterator akzeptiert:

%Vor%

Sie haben den zusätzlichen Vorteil, dass Sie alle Arten von Datenstrukturen wie

ausfüllen können %Vor%

usw.

BEARBEITEN (siehe Kommentar ...)

Um diese Funktion für die Initialisierung von Klassenmitgliedern zu verwenden, können Sie sie entweder im Konstruktor wie in

aufrufen %Vor%

oder mithilfe einer Wrapper-Funktion

%Vor%

Ich würde die erste Version aus Gründen der Leistung (und anderer) bevorzugen ...

    
MartinStettner 20.07.2010, 19:30
quelle
15

Warum nicht einfach den Vektor als Argument übergeben? Dann kann jeder Aufruf an denselben Vektor angehängt werden, ohne zu kopieren. Oder erstellen Sie eine Implementierungsklasse, die die Elemente in einem Mitgliedsobjekt akkumuliert.

    
Philipp 20.07.2010 19:23
quelle
8
  

PS: Ich zwinge mich nicht dazu, Vektor zu verwenden, irgendeinen anderen Container, der gleich gut funktioniert und verhindern kann, dass der potentielle große Kopiervorgang für mich in Ordnung ist.

Nun, wenn Sie list verwenden und a.splice(a.end(), b); aufrufen, vermeiden Sie den Kopiervorgang vollständig. A list ist im Allgemeinen eine verkettete Liste und nicht wie bei einem vector ein Array. Dies hat also viele Auswirkungen auf die Leistung und Nutzung. Aber Spleiß läuft in O (1), das ist ein netter Vorteil.

    
Brian 20.07.2010 19:29
quelle
2
%Vor%

Ich hoffe, das hat dir geholfen.

    
virious 20.07.2010 19:34
quelle
2

Verwenden Sie std :: list und hängen Sie an, indem Sie std :: list :: splice verwenden.

Von den Dokumenten für Spleiß :

  

Die Operation beinhaltet weder die Konstruktion noch die Zerstörung eines Elementobjekts und wird, abgesehen von der dritten Version, in konstanter Zeit ausgeführt.

    
cape1232 20.07.2010 19:32
quelle
1

Anstelle von

%Vor%

Sie können

tun %Vor%

und fahren Sie mit der Kopie fort:

%Vor%     
Alexandre C. 20.07.2010 19:21
quelle
0

Die rekursive Funktion muss alles mehrmals kopieren, O (Tiefe), um genau zu sein (d. h. alles in der Blattebene wird immer wieder kopiert, bis es die Wurzel erreicht).

Die beste Methode wäre das Aufteilen in zwei verschiedene Funktionen:

%Vor%     
sukru 20.07.2010 19:27
quelle
0

Wie wäre es mit einer Hilfsfunktion?

%Vor%     
David Gladfelter 20.07.2010 19:30
quelle
-1

Dies ist vielleicht nicht die einfachste mögliche Lösung, aber was ist mit etwas Ähnlichem wie C # 's StringBuilder?

Machen Sie eine list<vector<string> > , dann können Sie alle Vektoren, die Sie von Ihren Aufrufen erhalten, an scanDir() an die Liste anhängen.

Wenn Sie am Ende unbedingt einen einzelnen Vektor haben müssen, können Sie, sobald Sie einen neuen Vektor erstellt haben, diesen groß genug zuweisen, damit er nicht in der Größe geändert werden muss, und Ihr fertiges Produkt zusammenstellen.

Alternativ können Sie eine neue Klasse erstellen (falls erforderlich, die vom Vektor & lt; T & gt; abgeleitet wird) und intern die Liste & lt; vector & lt; T & gt; & gt; um die Elemente zu speichern. Dann würden Sie Ihre Iteratoren einfach durch die Elemente in der ersten Liste durchlaufen lassen, und wenn sie das Ende erreicht haben, gehen Sie zu den Elementen in der nächsten Liste und geben nur container :: end zurück, wenn Sie das Ende der letzten Liste erreicht haben.

    
Andrew Shelansky 20.07.2010 21:25
quelle
-1

Ich weiß, dass dies Ihre Frage nicht direkt beantwortet, aber in Bezug auf Ihr zugrunde liegendes Ziel möchten Sie vielleicht Ihre Funktion einfach in Bezug auf boost :: filesystem neu implementieren. Der Verzeichnis-Iterator ist bereits rekursiv, sodass Sie keine eigenen rekursiven Aufrufe durchführen müssen. Sie könnten einfach eine Liste in einer Schleife über den Iterator auffüllen. Es gibt eine Beispielimplementierung von ls: Ссылка

Sie erhalten außerdem den zusätzlichen Vorteil der (theoretischen) Plattformunabhängigkeit, der relativ breiten Akzeptanz (Fehler werden schneller durch mehr Adoption behoben), usw.

    
frankc 21.07.2010 03:43
quelle

Tags und Links