我正在尝试使用“联盟”合并2个列表,因此我摆脱了重复。以下是示例代码:
public class SomeDetail
{
public string SomeValue1 { get; set; }
public string SomeValue2 { get; set; }
public string SomeDate { get; set; }
}
public class SomeDetailComparer : IEqualityComparer<SomeDetail>
{
bool IEqualityComparer<SomeDetail>.Equals(SomeDetail x, SomeDetail y)
{
// Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y))
return true;
// Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
return x.SomeValue1 == y.SomeValue1 && x.SomeValue2 == y.SomeValue2;
}
int IEqualityComparer<SomeDetail>.GetHashCode(SomeDetail obj)
{
return obj.SomeValue1.GetHashCode();
}
}
List<SomeDetail> tempList1 = new List<SomeDetail>();
List<SomeDetail> tempList2 = new List<SomeDetail>();
List<SomeDetail> detailList = tempList1.Union(tempList2, SomeDetailComparer).ToList();
现在问题是我可以使用Union并仍然获取具有最新日期的记录(使用SomeDate属性)。记录本身可以在tempList1或tempList2中。
提前致谢
答案 0 :(得分:8)
真正适合此目的的操作是full outer join。 Enumerable
类具有内部联接的实现,您可以使用它来查找重复项并选择您喜欢的任何内容。
var duplicates = Enumerable.Join(tempList1, tempList2, keySelector, keySelector,
(item1, item2) => (item1.SomeDate > item2.SomeDate) ? item1 : item2)
.ToList();
keySelector
只是一个函数(可以是lambda表达式),它从类型SomeDetail
的对象中提取键。现在,要实现完整的外连接,请尝试以下方法:
var keyComparer = (SomeDetail item) => new { Value1 = item.SomeValue1,
Value2 = item.SomeDetail2 };
var detailList = Enumerable.Union(tempList1.Except(tempList2, equalityComparer),
tempList2.Except(tempList1, equalityComparer)).Union(
Enumerable.Join(tempList1, tempList2, keyComparer, keyComparer
(item1, item2) => (item1.SomeDate > item2.SomeDate) ? item1 : item2))
.ToList();
equalityComparer
应该是一个实现IEqualityComparer<SomeDetail>
的对象,并且有效地使用keyComparer
函数来测试相等性。
请告诉我这是否适合您。
答案 1 :(得分:1)
您必须能够告诉Union如何选择要使用的副本中的哪一个。除了编写自己的联盟之外,我不知道如何做到这一点。
答案 2 :(得分:1)
您不能使用标准Union
方法,但可以使用此特殊处理为Union
创建扩展方法List<SomeDetail>
,并且将使用此方法,因为签名更适合。< / p>
答案 3 :(得分:1)
为什么不直接使用HashSet&lt; T&gt;?
List<SomeDetail> tempList1 = new List<SomeDetail>();
List<SomeDetail> tempList2 = new List<SomeDetail>();
HashSet<SomeDetail> hs = new HashSet<SomeDetail>(new SomeDetailComparer());
hs.UnionWith(tempList1);
hs.UnionWith(tempList2);
List<SomeDetail> detailList = hs.ToList();
答案 4 :(得分:0)
合并通用列表
public static List<T> MergeListCollections<T>(List<T> firstList, List<T> secondList)
{
List<T> merged = new List<T>(firstList);
merged.AddRange(secondList);
return merged;
}
答案 5 :(得分:-1)
试试这个:
list1.RemoveAll(p => list2.Any(z => z.SomeValue1 == p.SomeValue1 &&
z => z.SomeValue2 == p.SomeValue1 &&
z => z.SomeDate == p.SomeDate));
var list3 = list2.Concat<SomeDetail>(list1).ToList();