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() });