通过这些对象的属性以外的其他内容对对象列表进行分组
Grouping list of objects by something other than properties of those objects
如何根据对象的属性以外的其他内容对对象列表进行分组?我需要对列表统计信息进行分组。列表中的每个对象都有 属性 字符串问题,对于每个问题,我想根据一些可能的答案对列表进行分组(每个组都有相同的可能答案),但这些可能的答案与统计数据没有直接关系class。
我想做这样的事情:
var customGroups = from stat in statistics group stat by new { PossibleAnswers = questions.SingleOrDefault(q => q.Text == stat.Question).PossibleAnswers };
foreach (var group in customGroups)
{
StatisticsWithSamePossibleAnswers.Add(group.ToList());
}
代码给出运行时异常:未将对象引用设置为对象的实例。
那么这样做的好方法是什么?我知道我总是可以使用嵌套的 foreach 循环,但是有什么更明智的方法吗?
类 统计数据和问题如下所示:
public class Statistics
{
public int ID { get; set; }
public int Year { get; set; }
public int Semester { get; set; }
public string Subject { get; set; }
public string Question { get; set; }
public bool IsAssociatedWithProfessor { get; set; }
public bool IsAssociatedWithAssistant { get; set; }
public string Answer { get; set; }
public int NumberOfAnswers { get; set; }
public double AnswerPercentage { get; set; }
public double? AM { get; set; }
public double? SD { get; set; }
}
public class Question
{
public int ID { get; set; }
public string Text { get; set; }
public bool IsAssociatedWithProfessor { get; set; }
public bool IsAssociatedWithAssistant { get; set; }
public virtual ICollection<PossibleAnswer> PossibleAnswers { get; set; }
public virtual ICollection<Results> Results { get; set; }
}
为了在 group by
查询中使用某些东西作为键,它必须是可以进行相等比较的东西。列表不被视为 "Equal" 只是因为它们具有相同的值,因此您需要将可能答案的列表转换为更具可比性的内容。在下面的代码示例中,我使用 string.Join()
生成以逗号分隔的答案字符串,但您可以根据需要进行调整。
var customGroups = from stat in statistics
group stat by string.Join(", ",
from q in questions
where q.Text == stat.Question
select q.PossibleAnswers);
foreach (var group in customGroups)
{
StatisticsWithSamePossibleAnswers.Add(group.ToList());
}
另请注意,通过摆脱 SingleOrDefault()
,我避免了当您遇到没有匹配问题的 stat
并得到空引用异常时 运行 遇到的问题.相反,您应该只获取一个空字符串作为分组依据。
HashSet<T>
可以使用正确的相等比较器进行分组。
var customGroups = statistics.GroupBy(
stat => new HashSet<PossibleAnswer>(questions.Single(q => q.Text == stat.Question).PossibleAnswers),
HashSet<PossibleAnswer>.CreateSetComparer());
请注意,这会忽略答案顺序和重复答案。这还假设 PossibleAnswer
默认情况下是可等式的。
如何根据对象的属性以外的其他内容对对象列表进行分组?我需要对列表统计信息进行分组。列表中的每个对象都有 属性 字符串问题,对于每个问题,我想根据一些可能的答案对列表进行分组(每个组都有相同的可能答案),但这些可能的答案与统计数据没有直接关系class。
我想做这样的事情:
var customGroups = from stat in statistics group stat by new { PossibleAnswers = questions.SingleOrDefault(q => q.Text == stat.Question).PossibleAnswers };
foreach (var group in customGroups)
{
StatisticsWithSamePossibleAnswers.Add(group.ToList());
}
代码给出运行时异常:未将对象引用设置为对象的实例。
那么这样做的好方法是什么?我知道我总是可以使用嵌套的 foreach 循环,但是有什么更明智的方法吗?
类 统计数据和问题如下所示:
public class Statistics
{
public int ID { get; set; }
public int Year { get; set; }
public int Semester { get; set; }
public string Subject { get; set; }
public string Question { get; set; }
public bool IsAssociatedWithProfessor { get; set; }
public bool IsAssociatedWithAssistant { get; set; }
public string Answer { get; set; }
public int NumberOfAnswers { get; set; }
public double AnswerPercentage { get; set; }
public double? AM { get; set; }
public double? SD { get; set; }
}
public class Question
{
public int ID { get; set; }
public string Text { get; set; }
public bool IsAssociatedWithProfessor { get; set; }
public bool IsAssociatedWithAssistant { get; set; }
public virtual ICollection<PossibleAnswer> PossibleAnswers { get; set; }
public virtual ICollection<Results> Results { get; set; }
}
为了在 group by
查询中使用某些东西作为键,它必须是可以进行相等比较的东西。列表不被视为 "Equal" 只是因为它们具有相同的值,因此您需要将可能答案的列表转换为更具可比性的内容。在下面的代码示例中,我使用 string.Join()
生成以逗号分隔的答案字符串,但您可以根据需要进行调整。
var customGroups = from stat in statistics
group stat by string.Join(", ",
from q in questions
where q.Text == stat.Question
select q.PossibleAnswers);
foreach (var group in customGroups)
{
StatisticsWithSamePossibleAnswers.Add(group.ToList());
}
另请注意,通过摆脱 SingleOrDefault()
,我避免了当您遇到没有匹配问题的 stat
并得到空引用异常时 运行 遇到的问题.相反,您应该只获取一个空字符串作为分组依据。
HashSet<T>
可以使用正确的相等比较器进行分组。
var customGroups = statistics.GroupBy(
stat => new HashSet<PossibleAnswer>(questions.Single(q => q.Text == stat.Question).PossibleAnswers),
HashSet<PossibleAnswer>.CreateSetComparer());
请注意,这会忽略答案顺序和重复答案。这还假设 PossibleAnswer
默认情况下是可等式的。