2017-02-26 4 views
-1

Je sais que le titre est désordonné comme l'enfer, je ne pourrais pas mieux le décrire en si peu de mots. Considérez ce code:Enlever une chaîne du vecteur <string> à l'index défini dans le vecteur <int>

#include <vector> 
#include <string> 

using std::string; 
using std::vector; 

int main() { 
    vector<string> s = { "foo", "bar", "random_word" }; 
    vector<int> i = { 0, 1 }; 
    for (int n = 0; n < i.size(); n++) { 
     s.erase(s.begin() + (i[n])); 
    } 
} 

Je voudrais supprimer des éléments de vecteur s basés sur les indices d'un autre vecteur i. Le programme actuel est plus compliqué que cela, mais en quelques mots, cette boucle se bloque (même si elle compile bien, en utilisant Visual C++).

EDIT: Ceci est le code réel qui a causé le problème:

// The vector in which the elements to be deleted are defined consists of 
// { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 } (the 
// name is i) 
// The other vector (s) consists of 
// { "Bancheri", "Bertagna", "Buzzoni", "Canepa", "De Vita", "Di Bella", 
// "Drago", "Esposito", "Fossati", "Francini", "Frontini", "Lorenzi", 
// "Marusceac", "Miscio", "Padovani", "Scarfo'", "Sieni", "Thea Cioni", 
// "Zunino" }; 
} 
for (int p = 0; p < i.size(); p++) { 
     s.erase(s.begin() + (s[i])) 
} 

// This is how I fixed it: 

{ 
     int r = i.size() - 1; 
     while (r > 0) { 
      s.erase(s.begin() + i[r]); 
      r -= 1; 
     } 
} 

Comme vous pouvez le voir, je simplement fait une autre boucle qui va dans le sens inverse.

+2

Vous devriez retirer de l'index le plus grand vers le bas. – Jarod42

+0

@ Rakete1111 oui, corrigé maintenant –

+3

Vous n'initialisez pas 'n'? –

Répondre

3

Le problème avec cette approche est qu'une fois qu'un élément à i[n] est supprimé, tous les index derrière lui reculent d'une unité.

Pour que ce programme fonctionne, triez i et passez du plus grand au plus petit.

+1

Exactement. 'std :: sort (i.begin(), i.end(), std :: plus ());' avant d'entrer dans la boucle. – WhozCraig

+0

@WhozCraig Je n'ai aucune idée de ce que ce code signifie –

+0

@TommasoTheaCioni Il trie le conteneur dans l'ordre décroissant. –

0

Comme nous l'avons souligné, la raison de l'écrasement est l'invalidation de l'index - tous les index supérieurs à i[n] doivent être décrémentés de 1 après la suppression de l'élément i[n]. En parcourant le conteneur d'index par ordre décroissant, vous vous assurez qu'il n'y a pas d'index supérieur à i[n] à un moment donné et qu'il n'est donc pas nécessaire de modifier d'autres index. Le tri i résout donc le problème.

Cependant en raison du fait que std::vector est un tableau contigu, l'effacement des éléments un par un n'est généralement pas une très bonne idée. Dans votre cas, il est assez facile de réorganiser le code pour faire tout l'effacement en une seule fois:

std::sort(i.begin(),i.end()); 
i.push_back(s.size()); //just to make sure the whole vector is visited 
auto iter = s.begin(); 
int current_index = 0; 
for(int index : i) 
{ 
    while(current_index < index) 
    { 
     *(iter++) = s[current_index++]; 
    } 
    current_index++; 
} 
s.erase(iter, s.end()); 

Dans le cas où vous pouvez vous permettre de représenter les éléments à supprimer par une certaine valeur, par exemple une chaîne vide, ça va mieux:

for(int index : i) 
    s[index] = ""; 
s.erase(std::remove(s.begin(),s.end(),""),s.end());