Join collections into new one model by Id.

Ant6729

Well-known member
Joined
Jan 22, 2019
Messages
56
Programming Experience
Beginner
Hello, everyone!

I would like to add all cars, that were made by person into a new collection of new models.

C#:
using System;
using System.Collections.Generic;
using System.Linq;

namespace JoinListsIntoNewModel
{
    public class Cars
    {
        public int Id { get; set; }
        public int MadeByPersonId { get; set; }
        public string MakerCompany { get; set; }
        public int ModelOfYear { get; set; }
        public string Color { get; set; }


    }

    public class MadeBy
    {
        public int Id { get; set; }
        public string PersonName { get; set; }
        public int YearOfProduction { get; set; }
        //public virtual ICollection<Cars> PersonCars { get; set; }
    }

    public class UnitedFullModel : MadeBy
    {
        public List<Cars> CarsCollection { get; set; }
    }

    internal class Program
    {
        public static void Main()
        {
            var cars = new List<Cars>
           {
               new Cars { Id = 1, MadeByPersonId = 1, MakerCompany = "Honda", ModelOfYear = 2000, Color = "Black" },
               new Cars { Id = 2, MadeByPersonId = 1, MakerCompany = "Suzuki", ModelOfYear = 1999, Color = "White" },
               new Cars { Id = 3, MadeByPersonId = 1, MakerCompany = "Toyota", ModelOfYear = 1988, Color = "Green" },
               new Cars { Id = 4, MadeByPersonId = 3, MakerCompany = "Kia", ModelOfYear = 2121, Color = "Blue" }
           };

            var madeBy = new List<MadeBy>
           {
               new MadeBy {Id = 1, PersonName = "Tim", YearOfProduction = 1998},
               new MadeBy {Id = 3, PersonName = "John", YearOfProduction = 2021},
               new MadeBy {Id = 4, PersonName = "Barbara", YearOfProduction = 1991 }
           };


            var fullElements = madeBy.Join(cars,
                                mad => mad.Id,
                                car => car.MadeByPersonId,
                                (mad, car) => new UnitedFullModel
                                {
                                    Id = mad.Id,
                                    PersonName = mad.PersonName,
                                    YearOfProduction = mad.YearOfProduction,
                                    //CarsCollection = cars.Where(x => x.MadeByPersonId == mad.Id)
                                }).ToList();

            Console.ReadLine();

        }
    }
}
 
But I do not understand, how to create a collection of items, that belong to the person, that created this car.
 
The Join() will return an enumerable of objects. You'll want to use GroupBy() to group by the MadeBy.Id to an enumerable of groups where each group was made by the particular person.

A better approach would be to use GroupJoin().

 
This is my attempt, but it is not correct.
C#:
            var query= persons.GroupJoin(cars,
                                person => person,
                                car => car.CarCreator,
                                (person, сarCollection) =>
                                    new UnitedFullModel
                                    {
                                        PersonName = person.PersonName,
                                        CarsCollection = сarCollection.Where(car => car.MadeByPersonId == person.Id)
                                    });
 
C#:
var byPerson = madeBy.GroupJoin(cars,
                                person => person.Id,
                                car => car.MadeByPersonId,
                                (person, cars) => new UnitedFullModel()
                                {
                                    Id = person.Id,
                                    PersonName = person.PersonName,
                                    YearOfProduction = person.YearOfProduction,
                                    CarsCollection = cars.ToList()
                                    });

foreach(var person in byPerson)
{
    Console.WriteLine($"{person.Id}: {person.PersonName} ({person.YearOfProduction}) made these cars:");
    foreach(var car in person.CarsCollection)
        Console.WriteLine($"{car.MakerCompany} {car.ModelOfYear} {car.Color}");
}

Output:
C#:
1: Tim (1998) made these cars:
Honda 2000 Black
Suzuki 1999 White
Toyota 1988 Green
3: John (2021) made these cars:
Kia 2121 Blue
4: Barbara (1991) made these cars:

 
Once again, thank you for your help)
Thanks for not answering right away so I can try to resolve my issue myself.
It is very important not to be tempted by a ready-made solution.
However, the first time I could not figure out how to use your example. And, of course, I tried to solve the problem directly.


C#:
            var listOfUnitedModels = new List<UnitedFullModel>();

            foreach (var person in persons)
            {
                if (cars.Any(carr => carr.MadeByPersonId == person.Id))
                {
                    var listCollectionOfCars = new List<Car>();

                    var unitedModel = new UnitedFullModel();

                    foreach (var car in cars)
                    {
                        if (person.Id == car.MadeByPersonId)
                        {
                            listCollectionOfCars.Add(car);

                            unitedModel.Id = person.Id;
                            unitedModel.PersonName = person.PersonName;
                            unitedModel.YearOfProduction = person.YearOfProduction;
                            unitedModel.CarsCollection = listCollectionOfCars;
                        }
                    }

                    listOfUnitedModels.Add(unitedModel);
                }
            }

            var result = listOfUnitedModels;

Thanks for your implementation! It works also. And looks better. And I take it into consideration.
 
Lines 17-20 never change. You can move it out of the loop.
C#:
var listOfUnitedModels = new List<UnitedFullModel>();

foreach (var person in persons)
{
    if (cars.Any(carr => carr.MadeByPersonId == person.Id))
    {
        var listCollectionOfCars = new List<Car>();
        foreach (var car in cars)
        {
            if (person.Id == car.MadeByPersonId)
            {
                listCollectionOfCars.Add(car);
            }
        }

        var unitedModel = new UnitedFullModel();
        unitedModel.Id = person.Id;
        unitedModel.PersonName = person.PersonName;
        unitedModel.YearOfProduction = person.YearOfProduction;
        unitedModel.CarsCollection = listCollectionOfCars;
        listOfUnitedModels.Add(unitedModel);
    }
}

var result = listOfUnitedModels;

And more refactoring:
C#:
var result = new List<UnitedFullModel>();
foreach (var person in persons)
{
    var listCollectionOfCars = new List<Car>();
    foreach (var car in cars)
    {
        if (person.Id == car.MadeByPersonId)
        {
            listCollectionOfCars.Add(car);
        }
    }
    
    if (listCollectionOfCars.Count > 0)
    {
        var unitedModel = new UnitedFullModel();
        unitedModel.Id = person.Id;
        unitedModel.PersonName = person.PersonName;
        unitedModel.YearOfProduction = person.YearOfProduction;
        unitedModel.CarsCollection = listCollectionOfCars;
        result.Add(unitedModel);
    }
}

And then to get the same result as the GroupJoin() like above which include persons without any cars:
C#:
var result = new List<UnitedFullModel>();

foreach (var person in persons)
{
    var listCollectionOfCars = new List<Car>();
    foreach (var car in cars)
    {
        if (person.Id == car.MadeByPersonId)
        {
            listCollectionOfCars.Add(car);
        }
    }
    
    var unitedModel = new UnitedFullModel();
    unitedModel.Id = person.Id;
    unitedModel.PersonName = person.PersonName;
    unitedModel.YearOfProduction = person.YearOfProduction;
    unitedModel.CarsCollection = listCollectionOfCars;
    result.Add(unitedModel);
}
 
I can't help myself...

C#:
var result = new List<UnitedFullModel>();
foreach (var person in persons)
{
    var listCollectionOfCars = cars.Where(car => person.Id == car.MadeByPersonId).ToList();
   
    var unitedModel = new UnitedFullModel()
    {
        Id = person.Id,
        PersonName = person.PersonName,
        YearOfProduction = person.YearOfProduction,
        CarsCollection = listCollectionOfCars
    }
    result.Add(unitedModel);
}

And then more...
C#:
var result = new List<UnitedFullModel>();
foreach (var person in persons)
{
    var unitedModel = new UnitedFullModel()
    {
        Id = person.Id,
        PersonName = person.PersonName,
        YearOfProduction = person.YearOfProduction,
        CarsCollection = cars.Where(car => person.Id == car.MadeByPersonId).ToList()
    }
    result.Add(unitedModel);
}

And once more...
C#:
var result = persons.Select(person =>
    new UnitedFullModel()
    {
        Id = person.Id,
        PersonName = person.PersonName,
        YearOfProduction = person.YearOfProduction,
        CarsCollection = cars.Where(car => person.Id == car.MadeByPersonId).ToList()
    })
    .ToList();
 
Back
Top Bottom