Split les colonnes d'un fichier.csv dans des listes de string

Résolu/Fermé
Utilisateur anonyme - Modifié le 4 janv. 2019 à 10:19
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 - 17 janv. 2019 à 19:27
Bonjour,

je cherche a remplir deux listes de string avec le contenue de deux colonnes d'un fichier.csv.
mon séparateur est un point-virgule et il s’agit des deux première colonnes du fichier.

voici ce que j'ai actuellement .

  List<string> column1 = new List<string>();
            List<string> column2 = new List<string>();

            column1.Add(string.Join(";\n", File.ReadAllLines(Globals.REFPATH).Skip(1).Where(x => x.Split(';').Length > 0).Select(x => x.Split(';')[0])));
            column2.Add(string.Join(";\n", File.ReadAllLines(Globals.REFPATH).Skip(1).Where(x => x.Split(';').Length > 1).Select(x => x.Split(';')[1])));

            Console.WriteLine("Column 1:");
            foreach (var element in column1)
                Console.WriteLine(element);

            Console.WriteLine("Column 2:");
            foreach (var element in column2)
                Console.WriteLine(element);


cela fonctionne mais certaine lignes des liste reste vierge sans raison (apparente).
quelqu'un peu me dire ce que je fait mal ?

merci de votre aide constante a chacun de mes soucis .


Configuration: Windobe / Chrome 71.0.3578.98

1 réponse

Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 931
Modifié le 4 janv. 2019 à 14:12
Bonjour

sans un exemple de fichier source qui ne marche pas très difficile de te répondre.

En plus utiliser des listes n'est pas cohérent du Join, un join ça construit une string à partir d'une collection.
Donc tes 2 résultats sont deux string.


Par contre sur le fond, l'erreur de base est de faire 2 listes.

C# est un langage tout objet, ce qui dans la pratique veut dire qu'il est optimisé pour que l'on écrive et utilise ses propres objets.

Si j'avais à charger en mémoire 2 informations d'un csv, je construirais une liste (une vraie) d'objets correspondant à mon besoin.

Pour l'exemple, on va dire que la colonne 1 est remplie (ou pas) d'entiers positifs et la 2 de texte.
Mon objet peut se résumer à
public DonneesAstrocurieux
{
     public int Entier {get; set;} //une propriété en lecture et écriture publiques qui contiendra l'entier d'une ligne
    public string Texte {get; set;} //une propriété qui en contiendra le texte

}


Je veux pouvoir initier cet en objet en faisant un new avec la ligne du csv en paramètre, je dois donc ajouter un constructeur. Dans ce constructeur, je vais gérer les cas où des "cases" du csv seraient manquantes ou vides.
Je décompose bien pour qu'il n'y ait pas d'ambiguïté.
    public class DonneesAstrocurieux
    {
        /// <summary>
        /// Constructeur, prenant en paramètre une ligne de csv
        /// </summary>
        /// <param name="LigneCsv">La ligne de csv qui sert à construire cette instanc</param>
        public DonneesAstrocurieux(string LigneCsv)
        {
            string[] donnees = LigneCsv.Split(';');
            Entier = -99;// -99 est la valeur indiquant une erreur
            Texte = string.Empty; //"" est la valeur indiquant une erreur

            if (donnees.Length > 0)//s'il y a au moins une donnée dans le tableau
            {
                int entier;
                if (int.TryParse(donnees[0], out entier))
                    Entier = entier; //si la "case" contient un entier, on l'affecte à la propriété  
            }


            if (donnees.Length > 1)//s'il y a au moins 2 données dans la tableau
                Texte = donnees[1];
        }

        public int Entier { get; set; } //une propriété en lecture et écriture publiques qui contiendra l'entier d'une ligne

        public string Texte { get; set; } //une propriété qui en contiendra le texte

    }


Enfin, pour afficher le contenue, je vais écrire ma propre méthode ToString, qui remplacera celle par défaut.


    public class DonneesAstrocurieux
    {
        /// <summary>
        /// Constructeur, prenant en paramètre une ligne de csv
        /// </summary>
        /// <param name="LigneCsv">La ligne de csv qui sert à construire cette instanc</param>
        public DonneesAstrocurieux(string LigneCsv)
        {
            string[] donnees = LigneCsv.Split(';');
            Entier = -99;// -99 est la valeur indiquant une erreur
            Texte = string.Empty; //"" est la valeur indiquant une erreur

            if (donnees.Length > 0)//s'il y a au moins une donnée dans le tableau
            {
                int entier;
                if (int.TryParse(donnees[0], out entier))
                    Entier = entier; //si la "case" contient un entier, on l'affecte à la propriété  
            }


            if (donnees.Length > 1)//s'il y a au moins 2 données dans la tableau
                Texte = donnees[1];
        }

        public int Entier { get; set; } //une propriété en lecture et écriture publiques qui contiendra l'entier d'une ligne

        public string Texte { get; set; } //une propriété qui en contiendra le texte

        /// <summary>
        /// ToString écrasant la méthode par défaut
        /// </summary>
        /// <returns></returns>
        /// <remarks>la méthode par défaut retourne le nom de la classe</remarks>
        public override string ToString()
        {
            return string.Format("L'entier est '{0}', le texte est '{1}'", Entier, Texte);
        }
    }


Le csv est
Entier;Texte
1;Texte 1
2;Texte 2;
;Texte 3
4
5;Texte 5
6;Texte 6
;
8;Texte 8
9;
10;Texte 10
;Texte 11

13;Texte 13


Pour charger et afficher les données
            List<DonneesAstrocurieux> donnees = File.ReadAllLines("astrocurieux.csv").Skip(1).Select(l => new DonneesAstrocurieux(l)).ToList();

            foreach (DonneesAstrocurieux item in donnees)
                Console.WriteLine(item.ToString());


Résultat
L'entier est '1', le texte est 'Texte 1'
L'entier est '2', le texte est 'Texte 2'
L'entier est '-99', le texte est 'Texte 3'
L'entier est '4', le texte est ''
L'entier est '5', le texte est 'Texte 5'
L'entier est '6', le texte est 'Texte 6'
L'entier est '-99', le texte est ''
L'entier est '8', le texte est 'Texte 8'
L'entier est '9', le texte est ''
L'entier est '10', le texte est 'Texte 10'
L'entier est '-99', le texte est 'Texte 11'
L'entier est '-99', le texte est ''
L'entier est '13', le texte est 'Texte 13'


De cette façon, quand il manque une valeur, l'instance existe quand même.
Ce qui n'est pas le cas avec ton codes et à chaque valeur manquante ou incorrecte tu as un décalage.

1
Utilisateur anonyme
17 janv. 2019 à 14:38
merci d'avoir pris le temps de rédigé une réponse aussi complète.

je pensais t'avoir répondue depuis longtemps mais je m’aperçois que non ...
sincèrement désolé.
0
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 931
17 janv. 2019 à 19:27
De rien
0