我有以下数据结构:
List<List<RecordItem>> combinedList = new List<List<RecordItem>>()
{
new List<RecordItem>()
{
new RecordItem() { fieldName = "StudentId", value = "S1" },
new RecordItem() { fieldName = "Maths", value = "90" },
new RecordItem() { fieldName = "Term", value = "1" },
},
new List<RecordItem>()
{
new RecordItem() { fieldName = "StudentId", value = "S1" },
new RecordItem() { fieldName = "Science", value = "70" },
new RecordItem() { fieldName = "Term", value = "1" },
}
};
我需要使用StudentId和Term对其进行分组,我能够按一个字段进行分组 - &gt; studentId(Credits:Enigmativity)但无法按多个字段分组(studentId和term)。 第一个问题是如何使用LINQ来获取另一个字段(term)?第二,如何为分组完成此代码。
List<List<RecordItem>> groupedList =
(
from records in combinedList
from student in records.Take(1)
from term in records.Take(?) // how do I get the term which is the 4th element???
let StudentId = student.value
let Term = term.value
let Subjects = records.Skip(1)
group Subjects by new
{
StudentId,Term
into gss
select new []
{
new RecordItem() { fieldName = "StudentId", value = gss.Key.StudentId },
new RecordItem() { fieldName = "Term", value = gss.Key.Term },
}.Concat(gss.SelectMany(x => x)).ToList()
).ToList();
答案 0 :(得分:1)
我无法真正理解这里发生了什么以及你在选择什么,但这是语法上正确的代码:
static void Main(string[] args)
{
List<List<RecordItem>> combinedList = new List<List<RecordItem>>()
{
new List<RecordItem>()
{
new RecordItem() { fieldName = "StudentId", value = "S1" },
new RecordItem() { fieldName = "Maths", value = "90" },
new RecordItem() { fieldName = "Term", value = "1" },
},
new List<RecordItem>()
{
new RecordItem() { fieldName = "StudentId", value = "S1" },
new RecordItem() { fieldName = "Science", value = "70" },
new RecordItem() { fieldName = "Term", value = "1" },
}
};
List<List<RecordItem>> groupedList =
(
from records in combinedList
from student in records.Take(1)
let StudentId = student.value
let Term = records.ToArray().ElementAt(3).value
let Subjects = records.Skip(1)
group Subjects by new
{
StudentId,
Term
}
into gss
select new[]
{
new RecordItem() { fieldName = "StudentId", value = gss.Key.StudentId },
new RecordItem() { fieldName = "Term", value = gss.Key.Term },
}.Concat(gss.SelectMany(x => x)).ToList()
).ToList();
}
答案 1 :(得分:1)
这就是你需要的:
List<List<RecordItem>> groupedList =
(
from records in combinedList
from student in records.Take(1)
let StudentId = student.value
from term in records.Skip(2).Take(1)
let Term = term.value
let Subjects = records.Skip(1).Take(1)
group Subjects by new { StudentId, Term } into gss
select new []
{
new RecordItem() { fieldName = "StudentId", value = gss.Key.StudentId },
new RecordItem() { fieldName = "Term", value = gss.Key.Term },
}.Concat(gss.SelectMany(x => x)).ToList()
).ToList();
尽管如此,这种数据结构在第二次会变得更糟。
答案 2 :(得分:0)
首先,您应该尝试使用比您拥有的更好的数据结构。说白了,使用List&gt;是蹩脚的,不得不依赖项目的顺序非常糟糕。做一些事情:将数据放在Dictionary<string,string>
中,甚至更好地放在自己的自定义类中。像
public class MyData
{
public string StudentId {get; set;}
public string Maths {get; set;}
public string Science {get; set;}
public string Term {get; set;}
}
我不确定这是你想要的数据结构,我几乎可以肯定其中一些字段应该是string
的其他字段,但你明白了。
根据您愿意实现的目标,您的数据结构合理,一切都会变得更加轻松。
现在,如果您拥有以前的数据结构,并希望将其投影到您刚创建的更好的数据结构,那就不难了。
投影到词典列表:
var dictionaries = groupedList.Select(l =>
l.ToDictionary(
item => item.fieldName ,
item => item.value)
).ToList();
现在您可以再次投影到更好的数据结构:
var myTypedList = dictionaries.Select(d => new MyData
{
StudentId = d["StudentId"],
Maths = d.ContainsKey("Maths") ? d["Maths"] : null,
Science = d.ContainsKey("Science") ? d["Science"] : null,
Term = d["Term"]
}).ToList();
现在,您可以轻松完成所需的分组:
var myResults = myTypedList.GroupBy(val => new {val.StudentId, val.Term})
.Select(group => new {
StudentId = group.Key.StudentId,
Term = group.Key.Term,
Maths = group.First(v => v.Maths != null).Maths,
Science = group.First(v => v.Science != null).Science
}).ToList();
请记住,当您为特定问题找到正确的数据结构时,大部分工作都将完成。尝试尽可能具体,它将使您的代码更容易编写和更容易阅读。试图变得“聪明”只与无意义的课程列表一起使用会让你无处可去。你在建模方面所做的工作是最重要的。