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

时间:2017-07-07 00:45:46

标签: c# list merge ienumerable

所以我有两个列表,它们对列表中的每个项目都有类似的属性。每个项目的格式为 -

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);
      }

}

2 个答案:

答案 0 :(得分:3)

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

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);

然后我们需要Zone var list3 = list1.Concat(list2) .GroupBy(a => a.Zone);

Sum

这将返回group the rows个实例的列表,我们可以使用它来获取区域(唯一键)并在其余字段上应用聚合函数。在我们的例子中,我们需要 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)); } 时,我们会看到它包含您要查找的结果:

nodejs ~/myapp.js 2>&1 | logger &
  

区域:110计数:3

     

区域:111计数:2

     

区域:115计数:3

     

区域:116计数:3

我没有在你的问题中看到任何要求“自定义函数”的内容,但在任何LINQ语句中添加都很容易。

答案 1 :(得分:0)

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

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}"));

<强>输出

enter image description here