2015-02-06 59 views
2

如何通过除这些对象的属性之外的其他属性对对象列表进行分组?我需要将List统计分组。列表中的每个对象都有属性字符串Question,并且对于每个Question都有一些可能的答案,我希望将列表分组(每个组具有相同的可能答案),但这些可能的答案与Statistics类没有直接关系。通过除这些对象的属性之外的其他属性对对象列表进行分组

我想要做这样的事情:

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; } 
} 
+1

你能提供一个像结构的小样本吗?我只是想确定我的理解正确 – CheGueVerra 2015-02-06 23:56:57

+0

目前,你的代码正在抛出,因为'questions'中没有匹配的元素。但我正在为一般情况寻找答案。 – recursive 2015-02-07 00:20:57

+0

我用一个Where替换了SingleOrDefault,并在最后注释了这部分.PossibleAnswers,似乎正在工作,但SingleOrDefault我不明白为什么你正在使用它 – CheGueVerra 2015-02-07 00:26:14

回答

3

HashSet<T>可以使用正确的相等比较器进行分组。

var customGroups = statistics.GroupBy(
    stat => new HashSet<PossibleAnswer>(questions.Single(q => q.Text == stat.Question).PossibleAnswers), 
    HashSet<PossibleAnswer>.CreateSetComparer()); 

请注意,这忽略了答案顺序和重复的答案。这也假定PossibleAnswer是默认等同的。

+0

一个很好的方法。它不太可能解决OP报告的错误,因为'.Single()'会在找不到匹配问题时抛出异常。但是这可能是数据的问题,而不是代码的问题。 – StriplingWarrior 2015-02-07 00:32:14

+0

@StriplingWarrior:这是真的,但一旦错误得到纠正,现有的代码将无法按预期进行分组,因为'List'不是可以等同的。 – recursive 2015-02-07 00:35:25

+0

https://msdn.microsoft.com/en-us/library/bb359438.aspx HashSet msdn – CheGueVerra 2015-02-07 00:37:40

2

为了在group by查询使用的东西为关键,它必须是东西,可以是平等的,相比较。仅仅因为它们具有相同的值,列表并不被视为“相等”,因此您需要将可能的答案列表转换为更具可比性的列表。在下面的代码示例中,我使用了string.Join()来产生一个以逗号分隔的答案字符串,但您可以根据需要调整它。还通过摆脱SingleOrDefault()

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()); 
} 

注意我避免你正在运行到,当你打一个stat是没有匹配的问题,并得到了一个空引用异常问题。相反,你应该得到一个空字符串来分组。

+0

是不是像这样var var customList = from stat在统计中 \t \t \t \t group stat by new {PossibleAnswers = questions.Where(q => q.Text == stat.Question)}; – CheGueVerra 2015-02-07 00:28:43

+0

@CheGueVerra:不,因为正如我上面所解释的,'PossibleAnswers'对于每个'stat'都将是一个新的'IEnumerable <>',所以即使它们具有相同的可能答案,也不会将任何东西组合在一起。 – StriplingWarrior 2015-02-07 00:30:22

+0

我仍然在LinqPad上玩它,不知道我得到它全部 – CheGueVerra 2015-02-07 00:31:21

相关问题