2009-11-05 57 views
3

我该如何用一个优雅的LINQ语句替换ConvertListToString(extensions)如何将此12行方法转换为单行LINQ表达式?

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(); 
     } 

    } 
} 

回答

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

这是比我更好的答案,因为这会将他更多的原始代码替换为Linq,而不仅仅是回答他的确切问题。我的投票在这里。 – 2009-11-05 12:49:35

+2

错!这是2行。 – 2009-11-05 12:58:08

+1

请注意,这也是一个很好的例子,说明为什么尽快接受答案并不是一个好主意。相反,即使您决定自己希望尽早使用哪个答案,也应该将问题留出一段时间,以查看是否有更好的答案冒泡到顶端。 – 2009-11-05 13:04:14

15

方法如下:

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

注意,我可能不会写为一行,而不是像这样:

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

如果你不只是介意直接使用Linq扩展方法,而不是Linq查询语法,可以使用以下代码:

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

另一种变化是只调用ToUpper最终字符串,而不是:

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

最后,在.NET 4.0中,String.Join终于支持IEnumerable<String>直接,所以这是可能的:

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

请注意,根据您的问题,这可能会导致重复。考虑一下如果您的原始文件名列表包含"filename.txt""filename.TXT",会发生什么情况,这些将被计为两个不同的扩展名。

在致电Distinct之前,应调用ToUpper来解决此问题。

代替原来的LINQ表达式+代码,我会重写整个事情到这一点:

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

如果您添加下面的实用程序方法,你的代码库中,可以进一步简化它:

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()); 
    } 
} 

,然后你的代码可以是这样的:

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

如何:

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

这个怎么样...

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

这确实是在同一行,我已经感动了“ToUpper的”出到最后的字符串,这样它对只调用一次。

很明显,你可以扔掉方法ConvertListToString和内联,如果你想。