2009-11-05 3 views
3

Comment puis-je remplacer ConvertListToString(extensions) par une instruction LINQ élégante?Comment puis-je transformer cette méthode de 12 lignes en une expression LINQ à une ligne?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace TestExtn2343 
{ 
    class Program 
    { 
     public static void Main(string[] args) 
     { 
      string[] files = { "test.txt", "test2.txt", 
           "test.as", "notes.doc", 
           "data.xml", "test.xml", 
           "test.html", "notes.txt", 
           "test.xls" }; 

      List<string> extensions = (from file in files 
          let index = file.LastIndexOf('.') + 1 
          select file.Substring(index)).Distinct().ToList<string>(); 

      Console.WriteLine("The kinds of file extensions used are {0}.", ConvertListToString(extensions)); 
      Console.ReadLine(); 
     } 

     public static string ConvertListToString(List<string> list) { 
      StringBuilder sb = new StringBuilder(); 
      int count = 1; 
      foreach (var listItem in list) 
      { 
       sb.Append(listItem.ToUpper()); 
       if (count != list.Count) 
        sb.Append(", "); 
       count++; 
      } 
      return sb.ToString(); 
     } 

    } 
} 

Répondre

17
var s = string.Join(", ", files.Select(file => Path.GetExtension(file)) 
    .Distinct(StringComparer.InvariantCultureIgnoreCase).ToArray()); 
+2

Ceci est une meilleure réponse que la mienne, car cela remplace plus de son code original avec Linq, plutôt que de simplement répondre à sa question exacte. Mon vote va ici. –

+2

Mauvais! C'est 2 lignes. –

+1

Notez qu'il s'agit également d'un très bon exemple de pourquoi il n'est pas judicieux d'accepter les réponses aussi rapidement que possible.Au lieu de cela, même si vous décidez de la réponse que vous souhaitez utiliser vous-même, laissez la question ouverte un peu plus longtemps pour voir si les meilleures réponses arrivent en haut. –

15

Voilà comment:

String s = String.Join(", ", (from extension in extensions select extension.ToUpper()).ToArray()); 

Remarque, je ne reviendrais probablement pas écrire cela comme une ligne plutôt comme ceci:

String s = String.Join(", ", 
    (from extension in extensions 
    select extension.ToUpper()).ToArray()); 

Si vous ne me dérange pas seulement aller pour les méthodes d'extension Linq directement, au lieu de la syntaxe de requête Linq, vous pouvez utiliser ceci:

String s = String.Join(", ", extensions.Select(e => e.ToUpper()).ToArray()); 

Une autre variante serait de simplement appeler ToUpper sur la chaîne finale à la place:

String s = String.Join(", ", extensions.ToArray()).ToUpper(); 

Et enfin, dans .NET 4.0, String.Join soutient enfin IEnumerable<String> directement, donc cela est possible:

String s = String.Join(", ", extensions).ToUpper(); 

Notez que selon votre question, cela pourrait entraîner des doublons. Considérez ce qui se passerait si votre liste originale de noms de fichiers contenait à la fois "filename.txt" et "filename.TXT", elles seraient comptées comme deux extensions distinctes.

L'appel à ToUpper doit être déplacé avant l'appel à Distinct pour résoudre ce problème.

Au lieu de l'expression Linq originale + code, je réécrire toute chose à ceci:

String[] distinctExtensions = files 
    .Select(fileName => Path.GetExtension(fileName).ToUpper()) 
    .Distinct() 
    .ToArray(); 
String distinctExtensionsAsString = String.Join(", ", distinctExtensions); 

Si vous ajoutez la méthode utilitaire suivante à votre bibliothèque de code, vous pouvez simplifier davantage:

public static class StringExtensions 
{ 
    public static String Join(this IEnumerable<String> elements, String separator) 
    { 
     if (elements is String[]) 
      return String.Join(separator, (String[])elements); 
     else 
      return String.Join(separator, elements.ToArray()); 
    } 
} 

puis votre code peut ressembler à ceci:

String distinctExtensionsAsString = files 
    .Select(fileName => Path.GetExtension(fileName).ToUpper()) 
    .Distinct() 
    .Join(", "); 
0

Que diriez-vous ceci:

String output = String.Join(", ",(from file in files 
    let index = file.LastIndexOf('.') + 1 
    select file.Substring(index)).Distinct().ToArray<string>()); 
1

Que diriez-vous ... ce

public static string ConvertListToString(List<string> list) 
{ 
    return list.Aggregate((x, y) => x + ", " + y).ToUpper(); 
} 

Ce qu'il fait dans une ligne, et je l'ai déplacé la « ToUpper » out sur la dernière chaîne de sorte qu'il est seulement appelé une fois. De toute évidence, vous pouvez alors jeter la méthode ConvertListToString et inline si vous le souhaitez.

Questions connexes