C# 使用linq聚合文本文件内容,以便对其进行分组
给出以下查询C# 使用linq聚合文本文件内容,以便对其进行分组,c#,linq,aggregate,C#,Linq,Aggregate,给出以下查询 var query = files .SelectMany(file => File.ReadAllLines(file)) .Where(_ => !_.StartsWith("*")) .Select(line => new { Order = line.Substring(32, 7), Delta = line.Subst
var query = files
.SelectMany(file => File.ReadAllLines(file))
.Where(_ => !_.StartsWith("*"))
.Select(line => new {
Order = line.Substring(32, 7),
Delta = line.Substring(40, 3),
Line = new String[] { line }
});
这显然会生成一个具有以下属性的对象列表:Order:string
、Delta:string
和Line:string[]
我有一个项目列表,如下所示
{ 1, 'A', {'line1'} },
{ 1, 'A', {'line2'} },
{ 2, 'B', {'line3'} },
{ 1, 'B', {'line4 } }
是否可以使用Linq聚合
或类似的功能结构来收集所有相邻的顺序
和增量
组合,同时累加行
因此,聚合是包含所有“行”的项的列表
{ 1, 'A', {'line1', 'line2'} }
{ 2, 'B', {'line3'} }
{ 1, 'B', {'line4'} }
由于聚合按顺序迭代,因此应该可以收集具有相同字段的所有相邻行
在循环中很容易做到这一点,但我正在尝试使用一组lambda来做到这一点。注意:不按相邻项对项目进行分组。 您可以使用简单的方法并结合以下步骤来产生所需的结果: 产生:
您将需要以下
GroupBy的变体:
public static class EnumerableExtensions
{
public class AdjacentGrouping<K, T> : List<T>, IGrouping<K, T>
{
public AdjacentGrouping(K key) { Key = key; }
public K Key { get; private set; }
}
public static IEnumerable<IGrouping<K, T>> GroupByAdjacent<T, K>(
this IEnumerable<T> sequence, Func<T, K> keySelector)
{
using (var it = sequence.GetEnumerator())
{
if (!it.MoveNext())
yield break;
T curr = it.Current;
K currKey = keySelector(curr);
var currentCluster = new AdjacentGrouping<K, T>(currKey) { curr };
while (it.MoveNext())
{
curr = it.Current;
currKey = keySelector(curr);
if (!EqualityComparer<K>.Default.Equals(currKey, currentCluster.Key))
{
// start a new cluster
yield return currentCluster;
currentCluster = new AdjacentGrouping<K, T>(currKey);
}
currentCluster.Add(curr);
};
// currentCluster is never empty
yield return currentCluster;
}
}
}
免责声明:函数groupbynextant
来自我自己的宠物项目,不从任何地方复制 我想您可以使用Enumerable.Aggregate
来实现这一点。不过,我得玩玩它才能让它工作。如果我吃过午饭回来时你还没有得到答案,我会看看我能想出什么办法。若这必须通过实体框架,那个么它可能是不允许的。是否使用EF?Aggregate
通过获取当前元素和累加器并创建新累加器来工作。这不是你正在做的,所以我不认为这是一个很好的匹配(虽然你可以让它工作,但在一个丑陋和难以阅读的方式)。您需要的是一个linq方法,它生成连续的“相等”元素,其中相等由委托确定。虽然您可以编写自己的循环(这只是对易于编写的循环的泛化),但没有内置的工具可以实现这一点。或者,看起来MoreLinq的groupnextant就是这么做的对不起,我之前链接的示例是按连续数字分组的,而不是相邻的。删除以避免混淆。也许这会有所帮助:我认为这不对-他想要相邻的分组。添加一个新元素,在末尾加上order=1,delta=“a”
。如果OP确认这不能解决他的问题,他将删除答案。我的理解是,我认为这从问题中很清楚,如果两个连续的元素具有相同的顺序和增量,那么它们应该分组。如果有具有相同顺序和增量的元素不是连续的,则不应将它们分组。@Chris的意思是仅将顺序和增量匹配的相邻元素分组,而不是集合中的所有顺序和增量感谢@vlad我希望有一种更简单的方法。。。但这太好了,谢谢你sharing@Jim当前位置前一段时间我也希望如此,但经过一些毫无结果的研究发现,自己推动其实更简单。
public static class EnumerableExtensions
{
public class AdjacentGrouping<K, T> : List<T>, IGrouping<K, T>
{
public AdjacentGrouping(K key) { Key = key; }
public K Key { get; private set; }
}
public static IEnumerable<IGrouping<K, T>> GroupByAdjacent<T, K>(
this IEnumerable<T> sequence, Func<T, K> keySelector)
{
using (var it = sequence.GetEnumerator())
{
if (!it.MoveNext())
yield break;
T curr = it.Current;
K currKey = keySelector(curr);
var currentCluster = new AdjacentGrouping<K, T>(currKey) { curr };
while (it.MoveNext())
{
curr = it.Current;
currKey = keySelector(curr);
if (!EqualityComparer<K>.Default.Equals(currKey, currentCluster.Key))
{
// start a new cluster
yield return currentCluster;
currentCluster = new AdjacentGrouping<K, T>(currKey);
}
currentCluster.Add(curr);
};
// currentCluster is never empty
yield return currentCluster;
}
}
}
var query = files
.SelectMany(file => File.ReadAllLines(file))
.Where(_ => !_.StartsWith("*"))
.Select(line => new
{
Order = line.Substring(32, 7),
Delta = line.Substring(40, 3),
Line = new String[] { line }
})
.GroupByAdjacent(o => new { o.Order, o.Delta })
.Select(g => new { g.Key.Order, g.Key.Delta, Lines = g.Select(o => o.Line).ToList() });