我正在尝试将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 :(得分:1)
可能的解决方案如下所示:
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());
您需要将Enumerable
更改为IEnumerable
。由于您正在创建匿名对象,因此您的解决方案会将匿名对象列表(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);
}
}
}
}