简体   繁体   中英

c# LINQ joining two lists

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM