LINQ查询—数据聚合(相邻组) [英] LINQ query — Data aggregation (Group Adjacent)

查看:67
本文介绍了LINQ查询—数据聚合(相邻组)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们上一个名为Cls的课程:

Let's take a class called Cls:

public class Cls
{
    public int SequenceNumber { get; set; }
    public int Value { get; set; }
}

现在,让我们用以下元素填充一些集合:

Now, let's populate some collection with following elements:


Sequence
Number      Value
========    =====
1           9
2           9
3           15
4           15
5           15
6           30
7           9

我需要做的是枚举序列号,并检查下一个元素是否具有相同的值.如果是,则汇总值,因此所需的输出如下:

What I need to do, is to enumerate over Sequence Numbers and check if the next element has the same value. If yes, values are aggregated and so, desired output is as following:


Sequence    Sequence
Number      Number
From        To          Value
========    ========    =====
1           2           9
3           5           15
6           6           30
7           7           9

如何使用LINQ查询执行此操作?

How can I perform this operation using LINQ query?

推荐答案

您可以在修改后的版本中使用Linq的GroupBy,该版本仅在两个项目相邻时才进行分组,因此很容易:

You can use Linq's GroupBy in a modified version which groups only if the two items are adjacent, then it's easy as:

var result = classes
    .GroupAdjacent(c => c.Value)
    .Select(g => new { 
        SequenceNumFrom = g.Min(c => c.SequenceNumber),
        SequenceNumTo = g.Max(c => c.SequenceNumber),  
        Value = g.Key
    });

foreach (var x in result)
    Console.WriteLine("SequenceNumFrom:{0} SequenceNumTo:{1} Value:{2}", x.SequenceNumFrom, x.SequenceNumTo, x.Value);

演示

结果:

SequenceNumFrom:1  SequenceNumTo:2  Value:9
SequenceNumFrom:3  SequenceNumTo:5  Value:15
SequenceNumFrom:6  SequenceNumTo:6  Value:30
SequenceNumFrom:7  SequenceNumTo:7  Value:9

这是对相邻项目进行分组的扩展方法:

This is the extension method to to group adjacent items:

public static IEnumerable<IGrouping<TKey, TSource>> GroupAdjacent<TSource, TKey>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector)
    {
        TKey last = default(TKey);
        bool haveLast = false;
        List<TSource> list = new List<TSource>();
        foreach (TSource s in source)
        {
            TKey k = keySelector(s);
            if (haveLast)
            {
                if (!k.Equals(last))
                {
                    yield return new GroupOfAdjacent<TSource, TKey>(list, last);
                    list = new List<TSource>();
                    list.Add(s);
                    last = k;
                }
                else
                {
                    list.Add(s);
                    last = k;
                }
            }
            else
            {
                list.Add(s);
                last = k;
                haveLast = true;
            }
        }
        if (haveLast)
            yield return new GroupOfAdjacent<TSource, TKey>(list, last);
    }
}

和使用的类:

public class GroupOfAdjacent<TSource, TKey> : IEnumerable<TSource>, IGrouping<TKey, TSource>
{
    public TKey Key { get; set; }
    private List<TSource> GroupList { get; set; }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return ((System.Collections.Generic.IEnumerable<TSource>)this).GetEnumerator();
    }
    System.Collections.Generic.IEnumerator<TSource> System.Collections.Generic.IEnumerable<TSource>.GetEnumerator()
    {
        foreach (var s in GroupList)
            yield return s;
    }
    public GroupOfAdjacent(List<TSource> source, TKey key)
    {
        GroupList = source;
        Key = key;
    }
}

这篇关于LINQ查询—数据聚合(相邻组)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆