C#将序列号应用于组项

时间:2016-03-17 14:48:10

标签: c# linq

我正在尝试对一组对象进行分组,按名称排序,但我还想在每个组中设置一个顺序的InstanceID属性,以便我有以下内容:

Name="A", InstanceID=0
Name="A", InstanceID=1
Name="A", InstanceID=2
Name="B", InstanceID=0
Name="C", InstanceID=0
Name="C", InstanceID=1
Name="C", InstanceID=2
Name="D", InstanceID=0
Name="D", InstanceID=1
Name="D", InstanceID=2
Name="D", InstanceID=3

我假设在GroupBy之后通过LINQ应用了一些投影但我不知道如何在SelectSelectMany中使用累加器或索引

我不想创建新集合,只修改现有集合,在每个元素上设置InstanceID

5 个答案:

答案 0 :(得分:4)

您可以GroupBy Name,然后为每个组设置InstanceID属性:

var groups = objects.GroupBy(m => m.Name);

foreach (var group in groups)
{
    int index = 0;
    foreach (var item in group)
        item.InstanceID = index++;
}

修改

您可以创建接收项目和索引的扩展方法ForEach

static class Extensions
{
    public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
    {
        foreach (var item in collection)
            action(item);
    }

    public static void ForEach<T>(this IEnumerable<T> collection, Action<T, int> action)
    {
        int index = 0;
        foreach (var item in collection)
            action(item, index++);
    }
}

并像这样使用它:

var groups = objects.GroupBy(m => m.Name);
groups.ForEach(g => g.ForEach((o, i) => o.InstanceID = i));

答案 1 :(得分:3)

您可以使用GroupBy,然后使用投射该索引的Select重载:

var groups = objects
    .GroupBy(x => x.Name)
    .Select(g => g.Select((obj, index) => new { Object = obj, Index = index }));

foreach(var grp in groups)
    foreach(var x in grp)
        x.Object.InstanceID = x.Index;

如果您对这些群组并不感兴趣,并且在确定索引后想要展平它们,您还可以使用SelectMany和一个循环:

var items = objects
    .GroupBy(x => x.Name)
    .SelectMany(g => g.Select((obj, index) => new { Object = obj, Index = index }));

foreach(var x in items)
    x.Object.InstanceID = x.Index;

答案 2 :(得分:2)

选择的重载会为您提供索引

var list = otherList.Select((model, index) => new { Index=index, ... })

在你的情况下,它可以像这样使用

list = list
        .OrderBy(m => m.Name)
        .GroupBy(m => m.Name)
        .SelectMany(g => g.Select((m, i) => new NameOfClass { InstanceID = i, Name = m.Name } ))
        .ToList();

答案 3 :(得分:0)

为了简单起见,我会使用这样的类:

public class StudentSubject
{
    public string Subject { get; set; }
    public string Student { get; set; }
    public int ID { get; set; }

}

列表必须以某种方式填充:

        var list = new List<StudentSubject>();
        list.Add(new StudentSubject
        {
            Subject = "Physics",
            Student = "Steve"
        });
        list.Add(new StudentSubject
        {
            Subject = "Physics",
            Student = "Sarah"
        });
....

然后遍历列表:

        var subjectGroups = from subjectStudent in list
                            group subjectStudent by subjectStudent.Subject;

        foreach(var subjectNameGroup in subjectGroups)
        {
            int id = 0;
            foreach (var studentSubject in subjectNameGroup)
            {
                studentSubject.ID = id;
                id++;
            }
        }

答案 4 :(得分:0)

使用查询表达式的解决方案:

class Person
{
    public string Name {get; set;}
    public int Instance {get; set;}
}

Person p1 = new Person {Name ="C"};
Person p2 = new Person {Name ="B"};
Person p3 = new Person {Name ="A"};
Person p4 = new Person {Name ="C"};
Person p5 = new Person {Name ="C"};
Person p6 = new Person {Name ="B"};

var persons = new List<Person>{p1, p2, p3, p4, p5, p6};

var result = from p in persons
             group p by p.Name into g orderby g.Key
             from gr in g.Select((x,i) => new {Value = x, Index = i})
             select gr;

result.ToList().ForEach(x => x.Value.Instance = x.Index);