Reputation: 1179
How to group list of objects by something other than properties of those objects? I need to group List statistics. Each object in the list has property string Question, and for each Question there are some possible answers by which I want to group the list (each group having same possible answers), but those possible answers are not directly related to Statistics class.
I want to do something like this:
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());
}
The code gives runtime exception: Object reference not set to an instance of an object.
So what is good way to do this? I know I can always use nested foreach loops, but is there anything wiser?
Classes Statistics and Question look like:
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; }
}
Upvotes: 2
Views: 102
Reputation: 86144
HashSet<T>
can be grouped using the right equality comparer.
var customGroups = statistics.GroupBy(
stat => new HashSet<PossibleAnswer>(questions.Single(q => q.Text == stat.Question).PossibleAnswers),
HashSet<PossibleAnswer>.CreateSetComparer());
Note that this ignores answer order and duplicate answers. This also assumes that PossibleAnswer
is equatable by default.
Upvotes: 3
Reputation: 156708
In order to use something as the key in a group by
query, it has to be something that can be equality-compared. Lists aren't considered "Equal" just because they have the same values in them, so you'll want to transform the list of possible answers into something more comparable. In the code sample below, I'm using a string.Join()
to produce a comma-separated string of the answers, but you can tweak that as necessary.
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());
}
Note also that by getting rid of SingleOrDefault()
I avoid the problem you were running into when you hit a stat
that had no matching questions, and got a null reference exception. Instead, you should just get an empty string to group by.
Upvotes: 2