I'm fighting while trying to join two lists together with LINQ.
What I got...
Class Person:
class Person
{
public string Name { get; private set; }
public int Age { get; private set; }
public bool Parent { get; private set; }
public bool Child { get; private set; }
public int Housenumber { get; private set; }
public Person(string name, int age, bool parent, bool child, int housenumber)
{
Name = name;
Age = age;
Parent = parent;
Child = child;
Housenumber = housenumber;
}
}
class House:
class House
{
public int Housenumber { get; private set; }
public int Rooms { get; private set; }
public string Color { get; private set; }
public House(int housenumber, int rooms, string color)
{
Housenumber = housenumber;
Color = color;
Rooms = rooms;
}
}
List of people:
private static List<Person> people = new List<Person>
{
new Person("Joel", 12, false, true, 1),
new Person("jana", 22, false, false, 2),
new Person("Housi", 45, true, false, 3),
new Person("Kurt", 25, false, false, 4),
new Person("Sebastian", 65, true, false, 1),
new Person("George", 14, false, true, 2),
new Person("Noel", 50, true, false, 3)
};
And a list of houses:
private static List<House> houses = new List<House>
{
new House(1, 4, "blue"),
new House(2, 2, "red"),
new House(3, 3, "black"),
new House(4, 1, "violett")
};
What I would like to to is to create a new list containing 'House' objects. But only those houses where at least two people live in!
I'm stuck here:
var houseWithMorePeople = from house in houses
join person in people
on house.Housenumber equals person.Housenumber
join person2 in people
on person.Housenumber equals person2.Housenumber
select house;
You can simply use Where
and Count
like this:
var result = houses
.Where(h => people.Count(p => p.Housenumber == h.Housenumber) >= 2)
.ToList();
There is no need for a join
. You can do it with Where
and Count
:
var houseWithMorePeople = houses.Where(house =>
persons.Count(person => person.Housenumber == house.Housenumber) > 1);
I'm not sure how to best convert Count()
into query language, so this is my best guess:
var houseWithMorePeople =
from house in houses
where (
from person in persons
where person.Housenumber == house.Housenumber
select person
).Count() > 1
select house;
I prefer the method syntax.
In query syntax with GroupBy
:
IEnumerable<House> houseWithMorePeople =
from house in houses
join person in people
on house.Housenumber equals person.Housenumber
group house by house.Housenumber into multiResidentsHouse
where multiResidentsHouse.Count() >= 2
select multiResidentsHouse.First();
If you want both informations, the house and it's residents:
var houseIncludingResidents =
from house in houses
join person in people
on house.Housenumber equals person.Housenumber
let resident = new { house, person }
group resident by house.Housenumber into multiResidentsHouse
where multiResidentsHouse.Count() >= 2
select new
{
House = multiResidentsHouse.First().house,
Residents = multiResidentsHouse.Select(x => x.person).ToList()
};
I'm really surprised by the answers saying "there is no need of join, simply do blah-blah". After all, what is more important - do it in a short way or do it in a right (and more performant) way?
You are on the right track. Just instead of a regular join
you need a group join , which as stated in the Enumerable.GroupJoin documentation:
Correlates the elements of two sequences based on key equality, and groups the results.
Once the data is correlated, you can perform efficient checks/aggregates on the related data set, like counting as in your case.
var houseWithMorePeople =
from house in houses
join person in people
on house.Housenumber equals person.Housenumber
into peopleInAHouse
where peopleInAHouse.Count() >= 2
select house;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.