IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Recherche d'un string dans un vector<string>


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    83
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2009
    Messages : 83
    Par défaut Recherche d'un string dans un vector<string>
    Bonjour à tous !

    Je bloque sur une partie de mon code.

    Je m'explique : J'ai un fichier CSV que je copie dans un vector<string> via le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void extractionCSV (ifstream& fichComp,vector<string>& vecCSV)
    {
    	string ligneCourante("");
     
    	if(fichComp)
    	{
    		fichComp.seekg(0,ios::beg);//on se place au début du fichier
    		while (getline(fichComp,ligneCourante))
    		{
    				vecCSV.push_back(ligneCourante);
    		}
    	}
    }
    Ensuite, l'idée est de rechercher un string nom contenue dans un élément de mon vecCSV.

    Par exemple, si
    nom="toto",
    et que
    vecCSV[0] = "tot1"
    vecCSV[1] = "tot2"
    vecCSV[2] = "le toto est à l'eau"
    vecCSV[3] = "tot6"
    etc...


    Alors, je veux pouvoir récupérer vecCSV[2].

    Je n'ai pas réussi à y parvenir, j'ai essayé avec std::find, mais il ne me renvoie rien (il me semble que find fait simplement une comparaison de type if(nom == vecCSV[i])).

    J'ai le bout de code suivant, qui ne marche donc pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    string rechercheLigneComp(string nom, std::vector<std::string> vecCSV)
    {
    	std::vector< std::string >::iterator it = vecCSV.begin();
    	for( ; ; )
    	{
    	   it = std::find(it, vecCSV.end(), nom);
    	   if ( it == vecCSV.end() )
    		  return "";
    	   else
    		  return vecCSV[std::distance( vecCSV.begin(), it++ )];
    	}
    }
    Si quelqu'un avait des pistes pour m'aiguiller, je suis preneur !

    Je précise par ailleurs que je dois effectuer la recherche de "nom" plusieurs centaines de fois. J'ai testé de rechercher "nom" directement dans le CSV (code ci-dessous), ça fonctionne bien mais la recherche est bien trop longue, c'est pourquoi je tente cette 2nde méthode.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    string rechercheLigneComp(string nom, ifstream& fichComp)
    {
    	string ligneCourante(""), ligneSortie("");
     
    	if(fichComp)
    	{
    		fichComp.seekg(0,ios::beg);//on se place au début du fichier
    		while (getline(fichComp,ligneCourante))
    		{
    			if(ligneCourante.find(nom) != std::string::npos)
    			{
    				ligneSortie=ligneCourante;
    				break;
    			}
    		}
    	}
    	return ligneSortie;
    }

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Salut

    Utilise find_if
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include <iostream>
    #include <vector>
    #include <algorithm>
     
    int main() {
      std::vector<std::string> vecCSV {{
        "tot1"
          , "tot2"
          , "le toto est a l'eau"
          , "tot6"
      }};
     
      std::string key = "toto";
      auto elem = std::find_if(begin(vecCSV), end(vecCSV), [&key](std::string const& elem) { return elem.find(key) != std::string::npos; });
      if (elem != end(vecCSV)) {
        std::cout << "Found \"" << (*elem) << "\" at pos " << std::distance(begin(vecCSV),elem) << "\n";
      }
      return 0;
    }

  3. #3
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    83
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2009
    Messages : 83
    Par défaut
    Nickel, c'est exactement ce que je voulais !

    Cela dit, cela ne règle pas mon problème initial : le temps d'exécution du programme. Il reste très long à exécuter...

    Pour information, mon fichier CSV fait environ 17000 lignes (donc mon vector vecCSV a 17000 éléments), et je dois le parcourir à peu près 800 fois.

    Je m'y prend peut-être pas de la manière optimale pour effectuer ces recherches, y-a-t-il une méthode plus optimisée ?

  4. #4
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Si l'ordre des éléments n'est pas contraint d'être celui du fichier, tu peux préférer un set.
    Tu peux aussi trier le vector, puis utiliser std::binary_search

  5. #5
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Hello,

    Si ce que tu recherches est bien délimité (UN mot par exemple), il est possible de stocker ton texte dans une (unordered)map.

    La création de cette map sera plus longue qu'une simple création de vecteur, mais la recherche devrait être plus rapide.

    Création de la map
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    typedef std::vector<int> line_t;
    typedef std::unordered_map<std::string, line_t> map_t;
     
    void insert(map_t & map, std::string const& word, int line) {
    	using std::begin;
    	using std::end;
     
    	auto it = std::find(begin(map), end(map), word);
    	if(it == end(map)) { // nouveau mot
    		it = map.insert(std::make_pair(word, line_t())).first;
    	}
    	it->second.push_back(line);
    }
     
    std::unordered_map<std::string, std::vector<int>> words;
    //vecCSV[0] = "tot1" devient
    insert(words, "tot1", 0);
    //vecCSV[2] = "le toto est à l'eau" devient
    insert(words, "le", 2);
    insert(words, "toto", 2);
    insert(words, "est", 2);
    insert(words, "à", 2);
    insert(words, "l'eau", 2);
    // etc...
    Et recherche
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // recherche de toto
    line_t const& search(map_t const& map, std::string const& word) {
    	using std::begin;
    	using std::end;
    	auto it = std::find(begin(map), end(map), word);
    	if(it == end(map)) {
    		return line_t(); // pas de problème de durée de vie vu qu'on retourne une ref constante ?
    	}
    	return it->second;
    }
     
    auto results = search(words, "toto");
    for(int i: results) {
    	std::cout << "'toto' à la ligne: " << i << '\n';
    }

  6. #6
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    83
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2009
    Messages : 83
    Par défaut
    Merci pour toutes ces pistes !

    Si ce que tu recherches est bien délimité (UN mot par exemple), il est possible de stocker ton texte dans une (unordered)map
    Hélas, non, ce n'est pas le cas, la chaîne que je recherche peut contenir des espaces, des tirets, etc.


    Si l'ordre des éléments n'est pas contraint d'être celui du fichier, tu peux préférer un set.
    Tu peux aussi trier le vector, puis utiliser std::binary_search
    le truc avec binary_search, c'est qu'il te renvoie simplement un booléen qui t'indique si la chaîne est présente dans mon vecteur (ou la sous-chaine dans mon cas, en adaptant la fonction Compare), mais pas à quel index. Je ne pourrais donc pas récupérer la chaine vecCSV[index] qui contient ma sous-chaine.

    De plus, pour effectuer le tri, je ne sais pas trop comment m'y prendre, sachant que ma sous-chaine n'est pas en 1ère place de la chaine dans le vecteur.

    Je reprécise, ça sera sans doute plus clair.

    1 - J'ai un fichier CSV d'entrée, de 17 000 lignes environ, au format suivant :
    101A,"TOTAL-X 204M","392","FR","22.60","33","406","398","","0","2015-02-17","commentaire eventuel"

    2 - J'ai des string que je récupère en parcourant un fichier *.txt (avec d'autres infos également). Ces strings correspondent en fait au 2ème champ du CSV (TOTAL-X 204M dans mon exemple).

    3 - Je voudrais donc récupérer la ligne complète du CSV qui correspond au string "courant".

    4 - Je fais ensuite un traitement par la suite sur ces données.


    Le point bloquant est donc la partie 3, où je n'arrive pas à récupérer rapidement la ligne du CSV.

Discussions similaires

  1. [Débutant] Recherche de 2 caractères dans une chaine de string
    Par Tornade8912 dans le forum VB.NET
    Réponses: 5
    Dernier message: 15/03/2015, 18h27
  2. Mettre le contenu d'une variable String dans un tableau de String
    Par patriot dans le forum Collection et Stream
    Réponses: 14
    Dernier message: 31/05/2011, 15h25
  3. Réponses: 2
    Dernier message: 18/09/2010, 22h33
  4. inserer une string dans une liste de string
    Par la_reine dans le forum Débuter avec Java
    Réponses: 5
    Dernier message: 14/05/2008, 08h07
  5. tableaux de String dans un vector
    Par aymanouch dans le forum Langage
    Réponses: 2
    Dernier message: 08/04/2007, 12h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo