Period|1|
AA|0|0|32.39|0|0|-0.12|
BB|0|-1794.62|
CC|Entity1|25|31.48|244.1|
DD|Entity2|25|0|0|
Period|2|
AA|0|0|32.39|0|0|-0.12|
BB|0|-1794.62|
CC|Entity1|25|31.48|244.1|
EE|Entity2|25|0|0|
FF|Entity3|25|0|0|
GG|Entity4|25|0|0|
HH|Entity5|25|0|0|
Period|3|
AA|0|0|32.39|0|0|-0.12|
BB|0|-1794.62|
将上述集合视为:
IEnumerable<IEnumerable<string>> data;
First Enumerable是每一行。 Second Enumerable是由分隔符|
分隔的每一行我想在每个时期对此进行分组:
预期结果:
Period1 (Group Key)
AA|0|0|32.39|0|0|-0.12|
BB|0|-1794.62|
CC|Entity1|25|31.48|244.1|
DD|Entity2|25|0|0|
Period2 (Group Key)
AA|0|0|32.39|0|0|-0.12|
BB|0|-1794.62|
CC|Entity1|25|31.48|244.1|
EE|Entity2|25|0|0|
FF|Entity3|25|0|0|
GG|Entity4|25|0|0|
HH|Entity5|25|0|0|
Period3 (Group Key)
AA|0|0|32.39|0|0|-0.12|
BB|0|-1794.62|
目前的实施:
foreach (var dataPerPeriod in data.Take(5))
{
yield return new DataPerPeriod(dataPerPeriod);
}
但是你可以看到只有第一个句号有5个元素,包括想成为关键元素(句号)。
因此我不明白如何解决这个问题。
答案 0 :(得分:4)
我已为您的DataPerPeriod制作了帮助类:
public class DataPerPeriod
{
public string Name { get; set; }
public List<IEnumerable<string>> Lines { get; set;}
}
我可以用这个查询聚合它:
var res = data.Aggregate(new List<DataPerPeriod>(), (a, b) =>
{
if (b.First() =="Period")
{
a.Add(new DataPerPeriod { Name = String.Join("", b),
Lines = new List<IEnumerable<string>>() });
}
else
{
a.Last().Lines.Add(b);
}
return a;
});
结果是:
答案 1 :(得分:2)
不是纯粹的LINQ,而是借助于“LINQ spirit”自定义泛型扩展方法,它允许您根据条件拆分(分区)序列:
public static class LinqExtensions
{
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, Func<T, bool> splitOn)
{
using (var e = source.GetEnumerator())
{
for (bool more = e.MoveNext(); more;)
{
var group = new List<T> { e.Current };
while ((more = e.MoveNext()) && !splitOn(e.Current))
group.Add(e.Current);
yield return group;
}
}
}
}
具体问题可以通过以下方式轻松解决:
IEnumerable<IEnumerable<string>> source = ...;
var result = source
.Split(e => e.FirstOrDefault() == "Period")
.Select(g => new
{
Key = g.First().Skip(1).FirstOrDefault(),
Elements = g.Skip(1)
});
答案 2 :(得分:1)
不是特别优雅(但是,你的数据集也不是这样)但是这样可行:
public static Dictionary<IEnumerable<string>,IEnumerable<IEnumerable<string>>> Parse(IEnumerable<IEnumerable<string>> input)
{
IEnumerable<string> key = null;
var rows = new List<IEnumerable<string>>();
var result = new Dictionary<IEnumerable<string>,IEnumerable<IEnumerable<string>>>();
foreach(var row in input)
{
if(row.First().StartsWith("Period"))
{
if(key != null)
result.Add(key,rows.AsEnumerable());
key = row;
rows = new List<IEnumerable<string>>();
}
else
{
rows.Add(row);
}
}
result.Add(key,rows);
return result;
}
答案 3 :(得分:0)
我已经解析了40年的文本文件了。如果我做不到,没人能。我的解决方案几乎与Jamiec的风格略有不同
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication43
{
class Program
{
const string FILENAME = @"c:\temp\test.txt";
static void Main(string[] args)
{
StreamReader reader = new StreamReader(FILENAME);
string inputLine = "";
Dictionary<string, List<string>> data = new Dictionary<string, List<string>>();
List<string> period = null;
while ((inputLine = reader.ReadLine()) != null)
{
inputLine = inputLine.Trim();
if (inputLine.Length > 0)
{
if (inputLine.StartsWith("Period"))
{
string key = inputLine.Replace("|", "");
period = new List<string>();
data.Add(key, period);
}
else
{
period.Add(inputLine);
}
}
}
}
}
}