2008-10-08 5 views
3

Est-il possible de nettoyer ce type de boucle à l'aide de LINQ?Comment puis-je LINQify cela?

List<Car> result; 
    List<string> makes; 
    List<string> models; 

    for (int i = 0; i < makes.Count() && i < models.Count(); i++) 
    { 
    result.Add(new Car() { Make = makes[i], Model = models[i] }); 
    } 

Fondamentalement, je suis à la recherche d'un moyen de rassembler plusieurs tableaux de champs individuels en un seul tableau d'objets composés de ces champs.

+0

pourquoi vous avez pas un constructeur de voiture avec 2 paramètres ... et modèle ...? –

+0

Je n'en avais pas dans ce cas mais cela nettoierait un peu les choses. J'aime bien la syntaxe ci-dessus, car elle vous permet de ne pas exposer les champs à deux endroits. – Luke

Répondre

7

Vous pouvez utiliser Enumerable.Range, comme ceci:

List<Car> result = Enumerable.Range(0, Math.Min(makes.Count, models.Count)) 
    .Select(i => new Car { Make = makes[i], Model = models[i] }).ToList(); 

Si makes et models contiennent toujours le même nombre d'éléments, vous pouvez utiliser une syntaxe plus compacte:

List<Car> result = makes.Select((make, i) => new Car { Make = make, Model = models[i] }).ToList(); 
+0

Cela fonctionne mais j'espérais qu'il y aurait quelque chose de plus compact sur le plan syntaxique. – Luke

+0

J'ai mis à jour la réponse pour montrer une surcharge de Select() qui permet une syntaxe plus compacte. –

+0

Besoin d'un ToList() sur la deuxième réponse. +1 –

1

Selon la façon dont vous avez souvent vont devoir écrire des requêtes LINQ contre ces tableaux, il peut être intéressant construire une classe qui enveloppe les tableaux et met en œuvre IEnumerable<Car>. Ensuite, votre code ressemble à ceci:

IEnumerable<Car> cars = new MyClass(makes, models); 
var result = from cars... 

Ce n'est pas particulièrement compliqué de construire ceci; il est seulement quatre méthodes simples (bien, six, si vous comptez les constructeurs) répartis dans deux classes (vous devez également mettre en œuvre IEnumerator<Car>).

Cette approche vous évite d'avoir à intégrer les détails de mise en œuvre dans toutes vos requêtes LINQ. De plus, si vous n'avez jamais fait cela, c'est vraiment quelque chose qui mérite d'être étudié. Être à l'aise de mettre en œuvre IEnumerable<T> étend considérablement l'espace des choses que vous pouvez facilement utiliser LINQ pour.

4

On dirait que vous avez vraiment besoin d'un nouvel opérateur de LINQ - celui qui n'a pas été inclus dans LINQ, un peu par hasard: Zip. Il faudrait essentiellement deux énumérables et retourner un seul énumérable qui apparie les entrées, jusqu'à ce que l'une ou l'autre des séquences d'origine soit terminée.

Je n'ai pas quelque chose comme ça dans ma manche, mais il ne faut pas prendre trop de temps pour écrire si vous êtes intéressé. Le code résultant serait quelque chose comme:

List<Car> cars = makes.Zip(models) 
         .Select(pair => new Car(pair.First, pair.Second)) 
         .ToList(); 

Laissez-moi savoir si vous seriez intéressé par cela et je vais coder en MiscUtil.

+0

En fait, ce serait parfait, encore mieux s'il pouvait "Zip" plus de 2 énumérables. – Luke

1
List<Car> result = makes 
        .Take(model.Count) 
        .Select((make, index) => new Car {Make = make, Model = models[index]}); 

Notez que cela fonctionne même si les marques et les modèles ne sont pas la même longueur.

Questions connexes