Home > OS >  Merging two lists: I have hardcoded two list and want to print both the list data where the conditio
Merging two lists: I have hardcoded two list and want to print both the list data where the conditio

Time:09-24

Merging two lists: I have hardcoded two lists and want to print both the list data where the conditions match. Please let me know how can I do?

I tried to use LINQ and got the solution but need to solve using for loop, please advise on the same.

    public IActionResult GetAllVehicleDrivers()
    {
        var VehicleList = new List<Vehicle>()

        {
            new Vehicle() { VehNum = "KA04AS1234", VehId = 1 },
            new Vehicle() { VehNum = "KA04AS5689", VehId = 2 },
            new Vehicle() { VehNum = "KA04AS9874", VehId = 3 },
            new Vehicle() { VehNum = "KA04AS5647", VehId = 4 },
            new Vehicle() { VehNum = "KA04AS7452", VehId = 5 },
        };

        var DriverList = new List<Driver>()
        {
            new Driver() { DriverName = "Gajaraj", DriverId = 123,  VehId = 1 },
            new Driver() { DriverName = "Tajar", DriverId = 245,  VehId = 5 },
            new Driver() { DriverName = "Pajara", DriverId = 363,  VehId = 3 },
            new Driver() { DriverName = "Haja", DriverId = 425,  VehId = 2 },
            new Driver() { DriverName = "Kaj", DriverId = 547,  VehId = 4 },
            new Driver() { DriverName = "Dajarajines", DriverId = 547,  VehId = 1 },
        };

        foreach (var i in VehicleList)
        {
            foreach (var j in DriverList)
            {
                if (i.VehId == j.VehId)
                {
                    List<dynamic> VehDriverList = new List<dynamic>()
                    {              i.VehId,
                                   i.VehNum,
                                   j.DriverId,
                                   j.DriverName
                    };
                    return Ok(VehDriverList);
                }
                else

                {
                    return NotFound();
                }
            }
        }
  }

}

CodePudding user response:

It seems your nested loop structure is incorrect, having the return statement inside the loop, immediately returns from the action method, also instantiating the List<> inside the loop, overrides the previous collection over and over. So, how about this?

// initialize the List outside the nested loop
List<dynamic> VehDriverList = new List<dynamic>();

foreach (var i in VehicleList)
{
    foreach (var j in DriverList)
    {
        if (i.VehId == j.VehId)
        {
            VehDriverList.Add(new List<dynamic>()
                {
                    i.VehId,
                    i.VehNum,
                    j.DriverId,
                    j.DriverName
                });
        }
    }
}

// return the results outside the loops
if (VehDriverList.Any())
{
    return Ok(VehDriverList);
}

return NotFound();
}

CodePudding user response:

So you have Vehicles and Drivers, and every Driver drives exactly one Vehicle, namely the Vehicle that the foreign key VehicleId refers to.

In theory there could be more Drivers on the same Vehicle. For instance if Driver [10] and Driver [11] both have a foreign key VehicleId = [20]. In that case, both Drivers will drive Vehicl [20].

In database terms, you will say that there is a one-to-many relation between Vehicles and Drivers: every Vehicle is driven by zero or more Drivers, every Driver drives exactly one Vehicle, namely the one and only Vehicle that the foreign key refers to.

If you have a one-to-many relation, like Customers with their zero or more Orders, Schools with their Students, or in your case Vehicles with their Drivers, there may be two kind of queries:

  • Give me all items with their zero or more sub-items; all Vehicles, each Vehicle with their Drivers
  • Give me subItems, each subItem with its one and only parent items; all Drivers, each Driver with its one and only Vehicle that he Drives.

In the latter case you'll use one of the overloads of Enumerable.Join. In the first case you'll use one of the overloads ofEnumerable.GroupJoin.

I almost always use the overload with a parameter resultSelector, which gives me the opportunity to precisely define which properties I want from the Drivers and the Vehicles.

Join: Drivers, each Driver with his Vehicle

var drivers = Drivers.Join(Vehicles, // Join Drivers and Vehicles

    driver => driver.VehicleId,      // from every driver take the foreign key
    vehicle => vehicle.Id,           // from every vehicle take the primary key

    // parameter resultSelector: from every driver with his one and only
    // matching vehicle, make one new:
    (driver, vehicle) => new
    {
         // Select the Driver properties that you plan to use:
         Id = driver.Id,
         Name = driver.Name,
         ...

         Vehicle = new
         {
             Id = vehicle.Id,
             Type = vehicle.Type,
             ...
         }
});

You won't get Vehicles that have no Drivers at all. After all: you are querying Drivers, not Vehicles!

My advice would be not to select the foreign key. You already know that it equals the primary key of the Vehicle.

GroupJoin: Vehicles, each Vehicle with its zero or more Drivers

var vehiclesWithTheirDrivers= Vehicles.GroupJoin(Drivers

    vehicle => vehicle.Id,           // from every vehicle take the primary key
    driver => driver.VehicleId,      // from every driver take the foreign key

    // parameter resultSelector: from every vehicle with its zero or more
    // drivers, make one new:
    (vehicle, driversOfThisVehicle) => new
    {
         // Select the Vehicle properties that you plan to use:
         Id = vehicle.Id,
         Type = vehicle.Type,
         ...

         Drivers = driversOfThisVehicle.Select(driver => new
         {
             // Select the Driver properties that you plan to use:
             Id = driver.Id,
             Name = driver.Name,
             ...

             // not needed, you already know the value:
             // VehicleId = driver.VehicleId,
          })
          .ToList(),
  });
  • Related