Search code examples
c#linqgroup-by

Create a nested list from a single records


my list:

{User = "UserName1", Car = "BMW", CarModel = "i3", Plate = "ExamplePlate1"},
{User = "UserName2", Car = "BMW", CarModel = "i3", Plate = "ExamplePlate2"},
{User = "UserName3", Car = "BMW", CarModel = "i8", Plate = "ExamplePlate3"},
{User = "UserName4", Car = "Audi", CarModel = "rs4", Plate = "ExamplePlate4"},
{User = "UserName5", Car = "Ford", CarModel = "Mustang", Plate = "ExamplePlate5"},
{User = "UserName6", Car = "Ford", CarModel = "Edge", Plate = "ExamplePlate6"}

I wish I had such a result:

{
Car = "BMW", 
       CarModel = {
              {CarModel = "i3", 
                            Users = {
                                   {Name = ""UserName1", Plate = "ExamplePlate1"},
                                   {Name = ""UserName2", Plate = "ExamplePlate2"}
                            },
              },
              {CarModel = "i8", 
                            Users = {
                                   {Name = ""UserName3", Plate = "ExamplePlate3"}
                            },
              },
       },      
},
{
       Car = "Ford",
       CarModel = {
              {CarModel = "Mustang", 
                            Users = {
                                   {Name = ""UserName5", Plate = "ExamplePlate5"}
                            },
              },
              {CarModel = "Edge", 
                            Users = {
                                   {Name = ""UserName6", Plate = "ExamplePlate6"}
                            },
              },
       },    
}
e.t.c

I did it via foreach in foreach in foreach but I don't think that's a very good approach. Is it possible to do it with linq or mapper?

I used nested(x3) foreachbut I don't think that's a very good approach


Solution

  • you can use LINQ

    List<CarItem> cars = ... your code
        
    List<CarGroup> carsGrouped = cars.GroupBy(x => new { x.Car, x.CarModel })
                          .Select(g => new CarGroup
                          {
                              Car = g.Key.Car,
                              CarModels = g.Select(cm => new CarModel
                              {
                                  CarModelName = cm.CarModel,
                                  Users = g.Select(x => new User { UserName = x.User, Plate = x.Plate }).ToList()
                              }).ToList()
                          })
                          .GroupBy(g => g.Car, (key, group) => new CarGroup
                          {
                              Car = key,
                              CarModels = group.Select(g => g.CarModels.First())
                          .ToList()
                          })
                          .ToList();
    

    output (in a json format)

    [
      {
        "Car": "BMW",
        "CarModels": [
          {
            "CarModelName": "i3",
            "Users": [
              {
                "UserName": "UserName1",
                "Plate": "ExamplePlate1"
              },
              {
                "UserName": "UserName2",
                "Plate": "ExamplePlate2"
              }
            ]
          },
          {
            "CarModelName": "i8",
            "Users": [
              {
                "UserName": "UserName3",
                "Plate": "ExamplePlate3"
              }
            ]
          }
        ]
      },
      {
        "Car": "Audi",
        "CarModels": [
          {
            "CarModelName": "rs4",
            "Users": [
              {
                "UserName": "UserName4",
                "Plate": "ExamplePlate4"
              }
            ]
          }
        ]
      },
      {
        "Car": "Ford",
        "CarModels": [
          {
            "CarModelName": "Mustang",
            "Users": [
              {
                "UserName": "UserName5",
                "Plate": "ExamplePlate5"
              }
            ]
          },
          {
            "CarModelName": "Edge",
            "Users": [
              {
                "UserName": "UserName6",
                "Plate": "ExamplePlate6"
              }
            ]
          }
        ]
      }
    ]
    

    classes

    public class CarItem
    {
        public string User { get; set; }
        public string Car { get; set; }
        public string CarModel { get; set; }
        public string Plate { get; set; }
    }
    public class CarGroup
    {
        public string Car { get; set; }
        public List<CarModel> CarModels { get; set; }
    }
    public class CarModel
    {
        public string CarModelName { get; set; }
        public List<User> Users { get; set; }
    }
    public class User
    {
        public string UserName { get; set; }
        public string Plate { get; set; }
    }