Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Mettre des données en forme en une requête LINQ

Losqu'on traite de LINQ, la majorité des exemples utilisent des sources de données "bien formées" : flux RSS (mon dernier billet), collections d'objets, etc. Mais dans la "vraie vie" les sources de données à traiter sont parfois moins "lisses", moins bien formées. LINQ peut aussi apporter son aide dans de tels cas pour transformer des données brutes en collection d'objets ayant un sens. C'est ce que nous allons voir dans ce billet.

Prenons un exemple simple : imaginons que nous récupérons une liste de rendez-vous depuis une autre application, cette liste est constituée de champs qui se suivent, les initiales de la personne, son nom et l'heure du rendez-vous. Tous les rendez-vous se suivent en une longue liste de ces trois champs mais sans aucune notion de groupe ou d'objet.

Pour simplifier l'exemple, fixons une telle liste de rendez-vous dans un tableau de chaînes :

string[] data = new[] { "OD", "Dahan", "18:00", "MF", "Furuta", "12:00", "BG", "Gates", "10:00" };

La question est alors comment extraire de cette liste "linéaire" les trois objets représentant les rendez-vous ?

La réponse passe par trois astuces :

  • L'utilisation de la méthode Select de LINQ qui sait retourner l'index de l'entité traitée
  • La syntaxe très souple de LINQ permettant d'utiliser des expressions LINQ dans les valeurs retournées
  • Et bien entendu la possibilité de créer des types anonymes

Ce qui donne la requête suivante :

var personnes = data.Select ( (s, i) => new
                                          {
                                             Value = s,
                                             Bloc = i / 3
                                          }
                                        ).GroupBy(x => x.Bloc)
                                        .Select ( g => new 
                                                    {
                                                      Initiales = g.First().Value,
                                                      Nom = g.Skip(1).First().Value,
                                                      RendezVous = g.Skip(2).First().Value
                                                     } );

L'énumération suivante : 

foreach (var p in personnes.OrderBy(p=>p.Nom)) Console.WriteLine(p);

donnera alors cette sortie console de toutes les personnes ayant un rendez-vous, classées par ordre alphabétique de leur nom :

{ Initiales = OD, Nom = Dahan, RendezVous = 18:00 }
{ Initiales = MF, Nom = Furuta, RendezVous = 12:00 }
{ Initiales = BG, Nom = Gates, RendezVous = 10:00 }

Voici des objets bien formés (on pourrait ajouter un DateTime.Parse à la création du champ RendezVous pour récupérer une heure plutôt qu'une chaîne) qui pourront être utilisés pour des traitements, des affichages, une exportation, etc...

LINQ to Object ajoute une telle puissance à C# que savoir s'en servir au quotidien pour résoudre tous les petits problèmes de développement qui se posent permet réellement d'augmenter la productivité, ce que tous les langages et IDE promettent falacieusement (aucune mesure de ce supposé gain n'existe). Ici, essayez d'écrire le même code sans LINQ, vous verrez tout suite que le gain de productivité et de fiabilité est bien réel, et que la maintenance aura forcément un coup moindre.

Pour d'autres infos, Stay Tuned !

Le projet VS 2008 : LinqChunk.zip (5,35 kb)

blog comments powered by Disqus