C# 基于数据顺序的分组

C# 基于数据顺序的分组,c#,sql,.net,linq,C#,Sql,.net,Linq,我有一组以下格式的数据 A A B A C B B C 我希望以这样一种方式对数据进行分组,即结果应该按字母表分组,并且应该基于顺序。例如,对于上述数据,输出应为 A - 2 B - 1 A - 1 C - 1 B - 2 C - 1 创建变量以跟踪最后一个字母和计数。然后在字母上循环并在字母更改时发出数据 List<char> letters = new List<char>() { 'A', 'A', 'B', 'A', 'C', 'B', 'B', 'C' };

我有一组以下格式的数据

A
A
B
A
C
B
B
C
我希望以这样一种方式对数据进行分组,即结果应该按字母表分组,并且应该基于顺序。例如,对于上述数据,输出应为

A - 2
B - 1
A - 1
C - 1
B - 2
C - 1

创建变量以跟踪最后一个字母和计数。然后在字母上循环并在字母更改时发出数据

List<char> letters = new List<char>() { 'A', 'A', 'B', 'A', 'C', 'B', 'B', 'C' };

char last = letters.First();
int count = 1;
foreach (char letter in letters.Skip(1))
{
    if (letter == last)
    {
        count++;
    }
    else
    {
        Console.WriteLine(last + " - " + count);
        last = letter;
        count = 1;
    }
}
Console.WriteLine(last + " - " + count);
List letters=newlist(){'A','A','B','A','C','B','B','C'};
char last=字母。First();
整数计数=1;
foreach(字母中的字符。跳过(1))
{
如果(字母==最后一个)
{
计数++;
}
其他的
{
Console.WriteLine(最后一次+“-”+计数);
最后一个=字母;
计数=1;
}
}
Console.WriteLine(最后一次+“-”+计数);
通过设置
last=letters.first()
,在循环外部处理第一个字符,因此
foreach
循环通过调用
letters.Skip(1)
以第二个字符开始


最后一个
控制台.WriteLine
用于处理最后一个字符块。

有一个很好的LINQ扩展,可以执行您想要的操作,由创建。可以使用以下扩展方法获取邻接分组:

 public static class LINQExtensions
{
    public static IEnumerable<IGrouping<TKey, TElement>> GroupAdjacentBy<TElement, TKey>(this IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer = null)
    {
        comparer = comparer ?? EqualityComparer<TKey>.Default;
        List<TElement> elements = null;
        TKey key = default(TKey);
        TKey lastKey = default(TKey);
        foreach (var x in source)
        {
            key = keySelector(x);
            if (elements != null && elements.Any() && !comparer.Equals(lastKey, key))
            {
                yield return new Grouping<TKey, TElement>(lastKey, elements);
                elements = null;
            }
            if (elements == null)
            {
                elements = new List<TElement>();
                lastKey = key;
            }
            elements.Add(x);
        }
        if (elements != null && elements.Any())
        {
            yield return new Grouping<TKey, TElement>(key, elements);
        }
    }

    public static IEnumerable<IGrouping<TElement, TElement>> GroupAdjacentBy<TElement>(this IEnumerable<TElement> source, IEqualityComparer<TElement> comparer = null)
    {
        return source.GroupAdjacentBy(keySelector: x => x, comparer: comparer);
    }

    // implement IGrouping
    public class Grouping<TKey, TElement> : IGrouping<TKey, TElement>
    {
        public TKey Key { get; private set; }
        private List<TElement> Elements { get; set; }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return ((IEnumerable<TElement>)this).GetEnumerator();
        }
        IEnumerator<TElement> IEnumerable<TElement>.GetEnumerator()
        {
            return ((IEnumerable<TElement>)Elements).GetEnumerator();
        }
        public Grouping(TKey key, List<TElement> elements)
        {
            Key = key;
            Elements = elements;
        }
    }
}

下面是我尝试用更实用的方式来做这件事(虽然不是很成功)。其思想是在前一个元素不等于当前元素时,按条件递增gorup:

    class ElementWithGroup
    {
        public string Element { get; set; }
        public int Index { get; set; }
        public int Group { get; set; }
    }

    static void Main(string[] args)
    {
        var list = new List<string>
        {
            "A",
            "A",
            "B",
            "A",
            "C",
            "B",
            "B",
            "C"
        };

        var helpList = list
            .Select((e, i) => new ElementWithGroup { Element = e, Index = i, Group = 0 })
            .ToList();

        var result = helpList
            .GroupBy(e => {
                var previous = e.Index == 0 ? null : helpList.ElementAt(e.Index - 1);
                if (previous != null)
                {
                    e.Group = previous.Element == e.Element ? previous.Group : previous.Group + 1;
                }
                return e.Group;
            });
    }
class-ElementWithGroup
{
公共字符串元素{get;set;}
公共int索引{get;set;}
公共int组{get;set;}
}
静态void Main(字符串[]参数)
{
变量列表=新列表
{
“A”,
“A”,
“B”,
“A”,
“C”,
“B”,
“B”,
“C”
};
var helpList=list
.Select((e,i)=>newelementwithgroup{Element=e,Index=i,Group=0})
.ToList();
var result=帮助列表
.GroupBy(e=>{
var-previous=e.Index==0?null:helpList.ElementAt(e.Index-1);
如果(上一个!=null)
{
e、 Group=previous.Element==e.Element?previous.Group:previous.Group+1;
}
返回e组;
});
}
我对这个解决方案不满意,我更愿意以迭代的方式来做,但也许它会帮助某些人。

试试这个:

string[] letters = new string[] { "A", "A", "B", "A", "C", "B", "B", "C" };

int gindex = 0;
var v = letters.Select((x, i) => { return (i == 0 || x == letters[i - 1]) ? new { L = x, G = gindex } : new { L = x, G = ++gindex }; }).GroupBy(x => x);

foreach (var x in v) {
    Console.WriteLine(x.Key.L + " - " + x.Count());
}

欢迎使用StackOverflow:如果您发布代码、XML或数据示例,请在文本编辑器中突出显示这些行,并单击编辑器工具栏上的“代码示例”按钮(
{}
),以精确地格式化和语法突出显示它!那么你也不需要那些乱七八糟的标签了!那么你想数一数跑步记录?
    class ElementWithGroup
    {
        public string Element { get; set; }
        public int Index { get; set; }
        public int Group { get; set; }
    }

    static void Main(string[] args)
    {
        var list = new List<string>
        {
            "A",
            "A",
            "B",
            "A",
            "C",
            "B",
            "B",
            "C"
        };

        var helpList = list
            .Select((e, i) => new ElementWithGroup { Element = e, Index = i, Group = 0 })
            .ToList();

        var result = helpList
            .GroupBy(e => {
                var previous = e.Index == 0 ? null : helpList.ElementAt(e.Index - 1);
                if (previous != null)
                {
                    e.Group = previous.Element == e.Element ? previous.Group : previous.Group + 1;
                }
                return e.Group;
            });
    }
string[] letters = new string[] { "A", "A", "B", "A", "C", "B", "B", "C" };

int gindex = 0;
var v = letters.Select((x, i) => { return (i == 0 || x == letters[i - 1]) ? new { L = x, G = gindex } : new { L = x, G = ++gindex }; }).GroupBy(x => x);

foreach (var x in v) {
    Console.WriteLine(x.Key.L + " - " + x.Count());
}