在 C# 中组合列表记录

Combine List records in C#

我有以下列表

List<List<RecordItem>> combinedList = new List<List<RecordItem>>();

public class RecordItem
    {
        public string fieldName { get; set; }
        public string value { get; set; }
    }

这个数据结构的样本:

[0] [0]fieldName = "StudentId", value = "S1"
    [1]fieldName = "Maths", value = "90"

[1] [0]fieldName = "StudentId", value = "S1"
    [1]fieldName = "Science", value = "70"

[2] [0]fieldName = "StudentId", value = "S2"
    [1]fieldName = "Maths", value = "60"

[3] [0]fieldName = "StudentId", value = "S2"
    [1]fieldName = "Science", value = "50"

我需要合并这些行以获得以下输出, 我不确定如何将 LINQ 与 LAMBDA 一起使用,因为这是一个二维对象列表。

var groupedList = combinedList.GroupBy(u => u.???).Select(grp => grp.ToList()).ToList();

[0] [0]fieldName = "StudentId", value = "S1"
    [1]fieldName = "Maths", value = "90"
    [2]fieldName = "Science", value = "70"

[1] [0]fieldName = "StudentId", value = "S2"
    [1]fieldName = "Maths", value = "60"
    [2]fieldName = "Science", value = "50"

谢谢,

以下是您应该如何在问题中呈现数据:

List<List<RecordItem>> combinedList = new List<List<RecordItem>>()
{
    new List<RecordItem>()
    {
        new RecordItem() { fieldName = "StudentId", value = "S1" },
        new RecordItem() { fieldName = "Maths", value = "90" },
    },
    new List<RecordItem>()
    {
        new RecordItem() { fieldName = "StudentId", value = "S1" },
        new RecordItem() { fieldName = "Science", value = "70" },
    },
    new List<RecordItem>()
    {
        new RecordItem() { fieldName = "StudentId", value = "S2" },
        new RecordItem() { fieldName = "Maths", value = "60" },
    },
    new List<RecordItem>()
    {
        new RecordItem() { fieldName = "StudentId", value = "S2" },
        new RecordItem() { fieldName = "Science", value = "50" },
    },
};

现在我可以这样做了:

List<List<RecordItem>> groupedList =
(
    from records in combinedList
    from student in records.Take(1)
    let StudentId = student.value
    let Subjects = records.Skip(1)
    group Subjects by StudentId into gss
    select new []
    {
        new RecordItem() { fieldName = "StudentId", value = gss.Key },
    }.Concat(gss.SelectMany(x => x)).ToList()
).ToList();

我得到这个结果:

此代码假定 StudentId 记录始终在第一位。如果不是,那么添加几个 .Where 子句来替换 .Take(1).Skip(1) 运算符并不需要太多。

        List<List<RecordItem>> result = combinedList
            .Select(l =>
                combinedList
                    .Where(ls =>
                        ls.Exists(r1 => r1.fieldName == "StudentId" && r1.value == l.First(r2 => r2.fieldName == "StudentId").value)
                    ).SelectMany(lz => lz.Select(lx=>lx)).GroupBy(r=>new { id = r.fieldName, v = r.value }).Select(r=>r.First()).ToList()
            )
            .GroupBy(l => l.First(r2 => r2.fieldName == "StudentId").value).Select(r => r.First()).ToList();

首先我们将 combinedList 的元素分组:

var grouped = from x in combinedList
              group x by x.Where(y => y.fieldName == "StudentId").Select(y => y.value).FirstOrDefault();

我们按找到的第一个 StudentId (x.Where(y => y.fieldName == "StudentId").Select(y => y.value).FirstOrDefault()) 对它们进行分组。

var res = (from x in grouped
           // We do a ToArray here because we will reuse the y
           // collection twice. In this way it isn't recalculated
           // every time. It isn't really necessary
           let y = x.SelectMany(z => z).ToArray()
           select y.Where(z => z.fieldName == "StudentId").Take(1).Concat(y.Where(z => z.fieldName != "StudentId")).ToArray())
          .ToArray();

然后通过SelectMany我们把它压平。

在每个组中,我们首先放置一个 StudentId 类型的元素,然后是所有其他非 StudentId

类型的元素