合并两个列表并在合并时应用自定义函数
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}"));
输出
所以我有两个列表,列表中的每个项目都具有相似的属性。每一项的格式为 -
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}"));
输出