Reputation: 522
I have the following class
public class Person
{
public string ID {get; set;}
public string Name {get; set;}
public string District {get; set;}
public string Level {get; set;}
}
Then on my function, I am writing a LINQ to group a list of Person, by District then by Level, into a new list of the same type (Person)
I want to write it in a way that i will not use var (making it an anonymous type) and new:
Something like
List<Person> persons; \\this already has values
List<Person> grpByP = persons
.GroupBy()
.ToList<Person>(); \\ Linq query to group persons list by District and Level
I just don't know how to write the grpByP LINQ query.
UPDATE: I want the ID and the Name be retained in the values of the grpByP variable because using anonymous type will only include the District and Level.
Any help will be appreciated.
Upvotes: 0
Views: 1403
Reputation: 50273
The question for which this one had been originally marked as duplicate already explains how to use GroupBy
. I'll address the second part: "converting to List<Person>
" and "not using var
".
First, about converting the result of GroupBy
to List<Person>
: you can't do that. The result of the GroupBy
operation is a IEnumerable<IGrouping<String,Person>>
(assuming you are grouping by a string
property), which is itself an IEnumerable
of IEnumerable<Person>
; each of these inner IEnumerable<Person>
corresponds to each of the keys found, and you can check the key for each case with the Key
property:
var grouped = persons.GroupBy(p => p.District);
foreach(var group in grouped)
{
Console.WriteLine($"People in disctrict {group.Key}:");
foreach(var person in group)
{
Console.WriteLine(person.Name);
}
}
You could go back to get the full list of ungrouped people, but I'd say that doesn't make much sense:
var ungrouped = grouped.SelectMany(g => g).ToList<Person>();
And about not using var
: you certainly could define the variable as IEnumerable<IGrouping<String,Person>>
, but I don't see what would be the benefit of doing that.
Edit: All of this doesn't apply if as other answers suggest what you actually want to do is to sort your data, not to group it.
Edit per your comment: "I want the ID and the Name be retained in the values of the grpByP variable because using anonymous type will only include the District and Level" - GroupBy
will not create anonymous objects, it will keep the original objects that you supplied (see my example above). Anonymous objects would be created only if you did something like .Select(p => new {p.Discrict})
in the resulting groups.
Upvotes: 0
Reputation: 6864
I think you're after something like this...
List<Person> persons = new List<Person>
{
new Person()
{
ID = "1",
Name = "Joe",
District = "Columbia",
Level = "10"
},
new Person()
{
ID = "2",
Name = "Beth",
District = "Columbia",
Level = "10"
},
new Person()
{
ID = "3",
Name = "Jim",
District = "Washington",
Level = "11"
}
}; //this already has values
var grpByP = persons
.GroupBy(p => new { p.District, p.Level })
.Select(g => new
{
g.Key,
People = g.ToList<Person>()
});
foreach (var g in grpByP)
{
Console.WriteLine("Group:");
Console.WriteLine(g.Key.District);
Console.WriteLine(g.Key.Level);
Console.WriteLine("People:");
foreach (Person p in g.People)
Console.WriteLine(p.Name);
Console.WriteLine();
}
Console.ReadLine();
Output:-
Group: Columbia 10 People: Joe Beth
Group: Washington 11 People: Jim
Upvotes: 2
Reputation: 136074
It sounds from comments like you just want to order your list by district, then by level. This is easy enough
List<Person> result = persons.OrderBy(p => p.District).ThenBy(p => p.Level).ToList();
Upvotes: 3