合并两个列表并在合并时应用自定义函数

Merge two lists and apply custom function while merging

所以我有两个列表,列表中的每个项目都具有相似的属性。每一项的格式为 -

public class ZoneOccupancy
{
    public virtual string ZoneId { get; set; }
    public virtual int CurrentOccupancy { get; set; }
}


ZoneId | CurrentOccupancy 

一个列表就像-

ZoneId | CurrentOccupancy 

110      2
111      1
115      3

另一个列表就像 -

ZoneId | CurrentOccupancy 

110      1
111      1
116      3

合并后我想要的是 -

ZoneId | CurrentOccupancy 

110      3
111      2
115      3
116      3 

所以我希望列表中的重复项合并为一个,但在此过程中,要添加的计数。

编辑:

list.Union(ParkingTagTicketQueryResult, ZoneComparer.Instance)
                         .GroupBy(z => z.ZoneId)
                         .Select(z => new ZoneOccupancy
                                        {
                                            ZoneId = z.First().ZoneId,
                                            CurrentOccupancy = z.Sum(row => row.CurrentOccupancy)


public class ZoneComparer : IEqualityComparer<ZoneOccupancy>
{
     public static readonly ZoneComparer Instance = new ZoneComparer();

     // We don't need any more instances
     private ZoneComparer() { }

     public int GetHashCode(ZoneOccupancy z)
     {
          return z.ZoneId.GetHashCode();
     }

     public bool Equals(ZoneOccupancy z1, ZoneOccupancy z2)
     {
          if (Object.ReferenceEquals(z1, z2))
          {
              return true;
          }

          if (Object.ReferenceEquals(z1, null) ||
              Object.ReferenceEquals(z2, null))
          {
              return false;
          }

          return z1.ZoneId.Equals(z2.ZoneId);
      }

}

首先让我们定义一个 class 来保存我们的数据:

class Datum
{
    public string Zone { get; set; }
    public int Count { get; set; }
}

并填充两个列表:

        var list1 = new List<Datum>();
        list1.Add(new Datum { Zone = "110", Count = 2 });
        list1.Add(new Datum { Zone = "111", Count = 1 });
        list1.Add(new Datum { Zone = "115", Count = 3 });

        var list2 = new List<Datum>();
        list1.Add(new Datum { Zone = "110", Count = 1 });
        list1.Add(new Datum { Zone = "111", Count = 1 });
        list1.Add(new Datum { Zone = "116", Count = 3 });

要加入两个列表,我们需要将它们连接起来:

        var list3 = list1.Concat(list2);

然后我们需要 group the rows by Zone:

        var list3 = list1.Concat(list2)
                         .GroupBy(a => a.Zone);

这将 return 一个包含 IGrouping 个实例的列表,我们可以使用它来获取区域(唯一键)并对其余字段应用聚合函数。在我们的例子中,我们想要计数的 Sum

        var list3 = list1.Concat(list2);
                         .GroupBy(a => a.Zone)
                         .Select(group => new Datum 
                                          {
                                              Zone = group.Key, 
                                              Count = group.Sum(row => row.Count) 
                                          }
                                );

当我们转储 list3 时,我们会看到它包含您要查找的结果:

        foreach (var item in list3)
        {
            Console.WriteLine(string.Format("Zone: {0} Count: {1}", item.Zone, item.Count));
        }

Zone: 110 Count: 3

Zone: 111 Count: 2

Zone: 115 Count: 3

Zone: 116 Count: 3

我在您的问题中没有看到任何需要 "custom function" 的内容,但可以很容易地在任何 LINQ 语句中添加。

一种方法是简单地从一个列表开始,然后对于另一个列表中的每个项目,如果没有匹配项则添加该项目,或者如果有匹配项则更新现有项目:

var list1 = new List<ZoneOccupancy>
{
    new ZoneOccupancy {ZoneId = 110, CurrentOccupancy = 2},
    new ZoneOccupancy {ZoneId = 111, CurrentOccupancy = 1},
    new ZoneOccupancy {ZoneId = 115, CurrentOccupancy = 3},
};

var list2 = new List<ZoneOccupancy>
{
    new ZoneOccupancy {ZoneId = 110, CurrentOccupancy = 1},
    new ZoneOccupancy {ZoneId = 111, CurrentOccupancy = 1},
    new ZoneOccupancy {ZoneId = 116, CurrentOccupancy = 3},
};

var mergedList = list1.ToList();

foreach (var item in list2)
{
    var match = mergedList.FirstOrDefault(i => i.ZoneId == item.ZoneId);
    if (match == null)
    {
        mergedList.Add(item);
    }
    else
    {
        match.CurrentOccupancy += item.CurrentOccupancy;
    }
}

// Output results
mergedList.ForEach(i => 
    Console.WriteLine($"Zone Id: {i.ZoneId}, Current Occupancy: {i.CurrentOccupancy}"));

输出