[英]Removing duplicates from a list with “priority”
给出这样的记录集合:
string ID1;
string ID2;
string Data1;
string Data2;
// :
string DataN
最初Data1..N为null,对于这个问题几乎可以忽略。 ID1和ID2都唯一地标识记录。 所有记录都有ID2; 有些还会有ID1。 给定一个ID2,有一个(耗时)方法来获得它的相应ID1。 给定一个ID1,有一个(耗时)方法来获取记录的Data1..N。 我们的最终目标是尽快为所有记录填写Data1..N。
我们的近期目标是(尽可能快地)消除列表中的所有重复项,并保留更多信息。
例如,如果Rec1 == {ID1 =“ABC”,ID2 =“XYZ”},并且Rec2 = {ID1 = null,ID2 =“XYZ”},则这些是重复的,但是我们必须专门删除Rec2并保留Rec1。
最后一个要求消除了删除Dups的标准方法(例如HashSet),因为他们认为“复制”的两面都是可互换的。
如何将原始列表分成3个包含所有数据的列表,包含ID1的列表和只包含ID2的列表。
然后做:
var unique = allData.Concat(id1Data.Except(allData))
.Concat(id2Data.Except(id1Data).Except(allData));
在ID2的基础上定义了相等性。
我怀疑有更有效的表达方式,但据我所知,基本的想法是合理的。 将初始列表拆分为三个只是使用GroupBy
(然后在每个组上调用ToList
以避免重复查询)。
编辑:可能更好的想法:像以前一样分割数据,然后执行:
var result = new HashSet<...>(allData);
result.UnionWith(id1Data);
result.UnionWith(id2Data);
我相信 UnionWith
保留现有元素而不是用新的但相同的元素覆盖它们。 另一方面,这没有明确规定。 明确定义它会很好...
(同样,要么基于ID2使您的类型实现相等,要么使用相等比较器创建哈希集,这样做。)
几个月前我遇到了类似的问题。
尝试这样的事......
public static List<T> RemoveDuplicateSections<T>(List<T> sections) where T:INamedObject
{
Dictionary<string, int> uniqueStore = new Dictionary<string, int>();
List<T> finalList = new List<T>();
int i = 0;
foreach (T currValue in sections)
{
if (!uniqueStore.ContainsKey(currValue.Name))
{
uniqueStore.Add(currValue.Name, 0);
finalList.Add(sections[i]);
}
i++;
}
return finalList;
}
这可能闻起来很多,但我认为如果你确保两个比较的对象出现相同,LINQ-distinct仍然适用于你。 以下比较器会这样做:
private class Comp : IEqualityComparer<Item>
{
public bool Equals(Item x, Item y)
{
var equalityOfB = x.ID2 == y.ID2;
if (x.ID1 == y.ID1 && equalityOfB)
return true;
if (x.ID1 == null && equalityOfB)
{
x.ID1 = y.ID1;
return true;
}
if (y.ID1 == null && equalityOfB)
{
y.ID1 = x.ID1;
return true;
}
return false;
}
public int GetHashCode(Item obj)
{
return obj.ID2.GetHashCode();
}
}
然后你可以在列表上使用它......
var l = new[] {
new Item { ID1 = "a", ID2 = "b" },
new Item { ID1 = null, ID2 = "b" } };
var l2 = l.Distinct(new Comp()).ToArray();
records.GroupBy(r => r, new RecordByIDsEqualityComparer())
.Select(g => g.OrderByDescending(r => r, new RecordByFullnessComparer()).First())
或者如果要合并记录,则使用Aggregate
而不是OrderByDescending/First
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.