У меня есть файл csv, подобный этому
A, 22, 23, 12
B, 32, 4, 33
C, 34, 3 ,33
Я хочу напечатать сумму и среднее значение для каждой строки и пропустить первый столбец. Как сделать в LINQ с помощью Lambda
У меня есть файл csv, подобный этому
A, 22, 23, 12
B, 32, 4, 33
C, 34, 3 ,33
Я хочу напечатать сумму и среднее значение для каждой строки и пропустить первый столбец. Как сделать в LINQ с помощью Lambda
var stuff = from l in File.ReadAllLines(filename)
let x = l.Split(new [] {',', ' '}, StringSplitOptions.RemoveEmptyEntries)
.Skip(1)
.Select(s => int.Parse(s))
select new
{
Sum = x.Sum(),
Average = x.Average()
};
Если вы читаете большие файлы, а использование памяти - проблема, тогда следующее будет работать лучше, используя .NET 4:
var stuff = from l in File.ReadLines(filename)
let x = l.Split(new [] {',', ' '}, StringSplitOptions.RemoveEmptyEntries)
.Skip(1)
.Select(s => int.Parse(s))
select new
{
Sum = x.Sum(),
Average = x.Average()
};
В обоих случаях переменная stuff
содержит перечисляемый, который фактически не будет выполняться до тех пор, пока вы не начнете читать с него (например, внутри цикла foreach
).
string csvFile = @"myfile.csv";
string[] lines = File.ReadAllLines(csvFile);
var values = lines.Select(l => new { FirstColumn = l.Split(',').First(), Values = l.Split(',').Skip(1).Select(v => int.Parse(v)) });
foreach (var value in values)
{
Console.WriteLine(string.Format("Column '{0}', Sum: {1}, Average {2}", value.FirstColumn, value.Values.Sum(), value.Values.Average()));
}
Попробуйте использовать эту старую, но все еще хорошую библиотеку: FileHelpers Library
Он очень прост в использовании:
char delimiter = ',';
var dt = FileHelpers.CsvEngine.CsvToDataTable(fileName,delimiter);
то просто выполните:
var rowStats = dt.AsEnumerable()
.Select(x => x.ItemArray.Select(y => Convert.ToInt32(y)))
.Select(x => new { avg = x.Average(), sum = x.Sum() });
foreach (var rowStat in rowStats)
{
Console.WriteLine("Sum: {0}, Avg: {1}", rowStat.sum, rowStat.avg);
}
string[] csvlines = File.ReadAllLines(@txtCSVFile.Text);
var query = from csvline in csvlines
let data = csvline.Split(',')
select new
{
ID = data[0],
FirstNumber = data[1],
SecondNumber = data[2],
ThirdNumber = data[3]
};
Я только что открыл библиотеку LinqToCsv, он все разбирает, а затем вы можете запрашивать объекты, подобные коллекциям, и поддерживает отложенное чтение:
http://www.codeproject.com/Articles/25133/LINQ-to-CSV-library
Привет вы ищете что-то вроде этого
var rows = new List<string> {"A, 22, 23, 12", "B, 32, 4, 33", "C, 34, 3 ,33"};
foreach (var row in rows) {
var sum = row.Split(',').Skip(1).Sum(x => Convert.ToInt32(x));
var avg = row.Split(',').Skip(1).Average(x => Convert.ToInt32(x));
}
Что-то вроде этого может быть:
var csv = @"A, 22, 23, 12
B, 32, 4, 33
C, 34, 3 ,33";
var lines =
csv.Split('\n').Select(x => x.Split(',').Skip(1).Select(n => int.Parse(n))).Select(x => new {Sum = x.Sum(), Average = x.Average()});
foreach (var line in lines)
{
Console.WriteLine("Sum: " + line.Sum);
Console.WriteLine("Average: " + line.Average);
}
В общем, я не предлагаю делать что-то подобное. Вы должны использовать полноразмерный CSV-ридер для анализа CSV файла, и вы должны включить обработку ошибок.
using System.IO
// turn file into IEnumerable (streaming works better for larger files)
IEnumerable<Tuple<int, int, int>> GetTypedEnumerator(string FilePath){
var File = File.OpenText(FilePath);
while(!File.EndOfStream)
yield return new Tuple<int, int, int>(
Int.Parse(File[1]),
Int.Parse(File[2],
Int.Parse(File[3])
);
File.Close();
}
// this lines would return the sum and avg for each line
var tot = GetTypeEnumerator(@"C:\file.csv").Select(l=>l.Item1 + l.Item2 + l.Item3);
var avg = GetTypeEnumerator(@"C:\file.csv").Select(l=> (l.Item1 + l.Item2 + l.Item3) / 3);
Потоковый апороасс позволит вам обрабатывать файлы laregr, потому что вам не нужно сначала загружать их в memeory. У нас нет VS, не проверял синтаксис, не компилировался, как есть.
С уважением, GJ
Черт, много ответов уже, нужно набирать быстрее!
На самом деле, в большинстве случаев вам следует избегать разбиения на основе ','
только потому, что у вас может быть кома в строке.
Я даю вам лучшее общее решение с использованием Regex и простое в использовании:
var stuff = File.ReadAllLines(csvFilePath)
.Skip(1) // For header
.Select(s => Regex.Match(s, @"^(.*?),(.*?),(.*?),(.*?),(.*?)$"))
.Select(data => new
{
Foo = data.Groups[1].Value,
Bar = data.Groups[2].Value,
One = data.Groups[3].Value,
Two = data.Groups[4].Value,
});
И вы можете найти более подробную информацию здесь fooobar.com/info/209886/...