在 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
类型的元素
我有以下列表
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