2014-10-18 156 views
0

我正在嘗試將LINQ查詢的輸出寫入文本文件。爲此,我正在使用擴展方法。將LINQ結果寫入文本文件

這是我的LINQ查詢:

var group = 
    from c in census_data 
    group c by c.state into g 
    join s in state_gdp on g.FirstOrDefault().state equals s.state 
    orderby s.gdp descending 
    select new 
    { 
     State = g.Key, 
     Count = g.Count(), 
     SavingsBalance = g.Average(x => x.savingsBalanceDouble), 
     GDP = s.gdp 
    }; 

這是我的擴展方法:

public static class CSVWriter 
{ 
    public static void write(this Enumerable e, string file) 
    { 
     using (System.IO.StreamWriter f = new System.IO.StreamWriter(file)) 
     { 
      foreach (var i in e) 
      { 
       f.WriteLine(i); 
      } 
     } 
    } 
} 

但是我得到的是說System.Linq.Enumerable沒有getEnumerator方法的錯誤。

回答

0

一個可能的解決方案可以是這樣的:

var result = 
    from c in census_data 
    group c by c.state into g 
    join s in state_gdp on g.FirstOrDefault().state equals s.state 
    orderby s.gdp descending 
    select new 
    { 
     State = g.Key, 
     Count = g.Count(), 
     SavingsBalance = g.Average(x => x.savingsBalanceDouble), 
     GDP = s.gdp 
    }; 

var buffer = new StringBuilder(); 
buffer.AppendLine("#key,name,sum,gdp"); 
result.ToList().ForEach(item => buffer.AppendLine(String.Format("{0},{1},{2},{3}", item.State, item.Count, item.SavingBalance, item.GDP))); 
File.WriteAllText("d:\\temp\\file.csv", buffer.ToString()); 

您需要更改EnumerableIEnumerable。由於您正在創建一個匿名對象,因此您的解決方案會將匿名對象列表(IEnumerable<anonymous>)傳輸到您將數據寫入文件的函數中,但無法根據需要格式化輸出。

一個可能的解決辦法是把要寫入文件的字符串緩衝區的線,然後寫的文字一次使用System.IO.File.WriteAllText方法:

// test data 
var data = new List<Int32> { 1, 20, 30, 40, 50, 70 }; 
// create a list of anonymous objects 
var result = data.Select (d => new 
{ 
    Count = d, 
    State = String.Format("Item {0}", d), 
    SavingBalance = d * 10 
}); 
// create the output text buffer 
var buffer = new StringBuilder(); 
// add header line 
buffer.AppendLine("#key,name,sum"); 
// add each result line 
result.ToList().ForEach(item => buffer.AppendLine(String.Format("{0},{1},{2}", item.Count, item.State, item.SavingBalance))); 
// write to file 
File.WriteAllText("d:\\temp\\file.csv", buffer.ToString()); 

的輸出是:

#key,name,sum 
1,Item 1,10 
20,Item 20,200 
30,Item 30,300 
40,Item 40,400 
50,Item 50,500 
70,Item 70,700 

其中@aravol和@StephneKennedy提到的解決方案將是這樣的:

public static class CSVWriter 
{ 
    public static void write<T>(this IEnumerable<T> e, string file) 
    { 
     using (System.IO.StreamWriter f = new System.IO.StreamWriter(file)) 
     { 
      foreach (var i in e) 
      { 
       f.WriteLine(i); 
      } 
     } 
    } 
} 

,並可以這樣使用:

result.write<object>(file); 

如前所述,這種解決方案的問題是,你不能格式化輸出,因爲你正在使用Object.toString方法,你不能格式化(默認輸出看起來像{ key = value, key = value, ... })。

如果您仍想將結果傳輸到另一個方法,則創建一個類型化類併爲每個結果條目創建一個對象(然後傳輸該列表)。一個例子類型的類可以是這樣的:

public class Placeholder 
{ 
    public String Name { get; set; } 
    public Int32 Index { get; set; } 
    public Double Sum { get; set; } 
} 

然後改變你的LINQ查詢創建的Placeholder一個新的對象,而不是匿名對象:

// test data 
var data = new List<Int32> { 1, 20, 30, 40, 50, 70 }; 
var result = data.Select (d => new Placeholder 
{ 
    Key = d, 
    Name = String.Format("Item {0}", d), 
    Sum = d * 10.0m 
}).ToList(); 
result.write<Placeholder>("d:\\temp\\file.csv"); 

而且你的擴展方法可以直接使用write(this IEnumerable<Placeholder>...)或者投射每個對象以使用類屬性:

public static class CSVWriter 
{ 
    public static void write<T>(this IEnumerable<T> e, string file) 
    { 
     using (System.IO.StreamWriter f = new System.IO.StreamWriter(file)) 
     { 
      foreach (var i in e) 
      { 
       f.WriteLine(((Placeholder)i).Sum); 
      } 
     } 
    } 
} 
+0

「您的解決方案將無法工作,因爲您無法傳輸匿名對象列表(IEnumera ble )將數據寫入文件的功能。「是的,你可以,我的例子就是這麼做的 - 編譯器足夠聰明,可以接受匿名的T.問題是匿名對象上沒有可用的ToString()來創建所需的輸出。 – 2014-10-18 17:14:20

+0

@StephenKennedy好點,謝謝。我改變了我的答案。 – pasty 2014-10-18 17:17:04

+0

我喜歡你的第一個解決方案。但是我怎樣才能選擇每個條目屬性(狀態,計數,...)?因爲在你的測試數據中只有一個整數列表,但我的數據不是那樣 – dabadaba 2014-10-18 17:25:09