从具有匹配ID的两个列表创建树的方法

本文关键字:两个 列表 创建 方法 ID | 更新日期: 2023-09-27 17:52:38

假设我有以下两个模型:

public class Order
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Location { get; set; }
    public string Street { get; set; }
    public IList<Appointment> Appointments { get; set; }
}
public class Appointment
{
    public Guid Id {get; set;}
    public DateTime StartDate {get; set;}
    public DateTime EndDate {get; set;}
    public Guid OrderId { get; set; }
}

我有一个包含Order项的列表(所有的appointment列表都为空)和一个包含所有约会的列表,我不知道如何匹配这两个列表中的元素,以便获得包含所有相应约会的Order对象(基于OrderId)。

我怎样才能有效地做到这一点?我不想遍历所有订单,并分配相应的约会。

从具有匹配ID的两个列表创建树的方法

首先,通过OrderId创建Appointment的字典:

var appointmentByOrderId = appointments
    .GroupBy(a => a.OrderId)
    .ToDictionary(g => g.Key, g => g.ToList());

然后遍历Order s的列表,并将Appointments设置为字典中的列表:

foreach (var order in orders) {
    List<Appointment> appointmentList;
    if (appointmentByOrderId.TryGetValue(order.Id, out appointmentList) {
        order.Appointments = appointmentList;
    } else {
        order.Appointments = new List<Appointment>();
    }
}

else分支是可选的。如果您不希望将空列表设置为具有空约会列表的订单,则可以删除该列表。

一种方法是将两个列表"group join"并投影一个新的集合:

var neworders = 
    from o in orders
    join a in appointments
      on o.Id equals a.OrderId 
      into g
    select new Order
    {
       Id = o.Id,
       Name = o.Name,
       Location = o.Location,
       Street = o.Street,
       Appointments = g.ToList()
    };

显然,这会创建新的 Order对象-如果不希望这样做,另一种选择是循环遍历所有订单并"附加"匹配的约会-使用ToLookup对它们进行预分组:

var groups = appointments.ToLookup(a => a.OrderId);
foreach(var o in orders)
    o.Appointments = groups[o.Id].ToList();

构建一个Dictionary<Guid, Order>,并用您的所有订单填充它。然后浏览约会列表,并按适当的顺序添加。例如(假设您有一个名为Orders的列表和一个名为Appointments的列表):

var OrdersDictionary = Orders.ToDictionary(o => o.Id, o => o);
foreach (var appt in Appointments)
{
    OrdersDictionary[appt.OrderId].Appointments.Add(appt);
}

可能有一种LINQ方法可以在单个语句中完成所有的rollup,但是我没有花时间来解它。